Mysql-toiminnot päivämäärän ja ajan kanssa työskentelemiseen. Kalenteritietotyypit MySQL:ssä: käyttöominaisuudet


tämän artikkelin julkaiseminen on sallittua vain linkin kautta artikkelin kirjoittajan verkkosivustolle

Kuten tiedät, kaikki päivämäärät tallennetaan mysql:iin käänteisessä järjestyksessä vuosi-kuukausi-päivä (2008-10-18), joskus jopa ilman erotinta (20081018).
Päivämäärän näyttämiseksi sinun on muutettava se normaaliin luettavaan muotoon.

On olemassa kaksi muuntamismenetelmää, tehokas ja ei kovin tehokas.
Tehoton tapa on, kun mysql:n päivämäärätulostus muunnetaan käyttämällä php:tä.
Itse tein tämän pitkään aikaan. Ennen näyttämistä käänsin jokaisen päivämäärän päinvastaiseksi käyttämällä php-toimintoa.
Jos muunnosten määrä ei ole suuri, voit kääntää päivämäärän PHP:llä, siinä ei ole mitään vikaa, mutta jos sinun on vedettävä kymmeniä tai satoja tuhansia tietueita ja muutettava päivämäärä jokaisessa, niin tietysti muuntaminen päivämäärät mysql:llä ovat paljon nopeampia.

Mysql:ssä on loistava funktio nimeltä DATE_FORMAT(), se on hyvin samanlainen kuin php-toiminto Päivämäärä().
Tässä on esimerkki käytöstä

SELECT DATE_FORMAT("2008-11-19","%d.%m.%Y");
tulos

Kaikki on hyvin yksinkertaista ja nopeaa, päivämääriä ei tarvitse muuttaa php:n avulla.
Tässä on luettelo tämän toiminnon määritelmistä

Determinantti Kuvaus
%M Kuukauden nimi (tammikuu...joulukuu)
%W Viikonpäivän nimi (sunnuntai...lauantai)
%D Kuukauden päivä englanninkielisellä jälkiliitteellä (0st, 1st, 2nd, 3rd jne.)
%Y Vuosi, päivämäärä, 4 numeroa
%y Vuosi, päivämäärä, 2 numeroa
%X Vuosi viikolle, jossa sunnuntaita pidetään viikon ensimmäisenä päivänä, numero, 4 numeroa, käytetään "%V" kanssa
%x Vuosi viikolle, jossa sunnuntaita pidetään viikon ensimmäisenä päivänä, numero, 4 numeroa, käytetään "%v" kanssa
%a Viikonpäivän lyhennetty nimi (su...la)
%d Kuukauden päivä, numero (00..31)
%e Kuukauden päivä, numero (0..31)
%m Kuukausi, päivä (00..12)
%c Kuukausi, päivämäärä (0..12)
%b Kuukauden lyhennetty nimi (tam...joulukuu)
%j Vuoden päivä (001..366)
%H Tunti (00..23)
%k Tunti (0..23)
%h Tunti (01..12)
%I Tunti (01..12)
%l Tunti (1..12)
%i Minuutit, numero (00..59)
%r Aika, 12 tunnin muoto (tt:mm:ss M)
%T Aika, 24 tunnin muoto (tt:mm:ss)
%S Sekuntia (00..59)
%s Sekuntia (00..59)
%p Aamulla vai illalla
% w Viikonpäivä (0=sunnuntai..6=lauantai)
%U Viikko (00..53), jolloin sunnuntai on viikon ensimmäinen päivä
%u Viikko (00..53), jossa maanantaina pidetään viikon ensimmäinen päivä
%V Viikko (01..53), jolloin sunnuntai on viikon ensimmäinen päivä. Käytetään "%X":n kanssa
%v Viikko (01..53), jossa maanantaina pidetään viikon ensimmäinen päivä. Käytetään "%x":n kanssa
%% Kirjaimellinen "%".

Kommentit

27.11.2008 ----
Hei shaitan!!!
Itse olen työskennellyt php:n ja mysql:n parissa viisi vuotta, ja koko ajan vaihdoin päivämäärää php:ssä...
Minulle ei edes tullut mieleen, että sisäänrakennettua mysql-toimintoa olisi helpompi käyttää

28.11.2008 Zheka
Samoin! Olen aina käyttänyt php-toimintoa

12.3.2008 Sergei
No, yleisesti ottaen, käyttääkö kukaan edes tätä lähestymistapaa?
Vai käyttävätkö kaikki php:tä päivämäärän kääntämiseen?
Itse en ole koskaan vaihtanut päivämäärää mysqlissa, teen silti kaiken php:ssä

28.6.2009 Ilja
Valitettavasti mikään ei toiminut :(

08.07.2009 Vitaly
Hienoa, kiitos ominaisuudesta. Ihmettelen, mitä muita naarmuja siellä on?

14.07.2009 DSaint
Kiitos, se auttoi paljon. Jää vain näyttää kuukauden nimi venäjäksi)

28.07.2009 Vlad
mysql=>PHP
valitse unix_timestamp(aloituspäivämäärä) alkamispäivämääräksi_php
php-koodi
päivämäärä("d.m.Y",$row["aloituspäivä_php"])

PHP=>MySQL
päivitystaulukko asetettu aloituspäivämäärä=DATE_FORMAT(STR_TO_DATE("19/12/2009 18:35:22 PM","%d.%m.%Y %H:%i"),"%Y.%m.%d % Hei")

18.08.2009 Vieras
2: DSaint
Siinä on niin upea toiminto:
ELT(KUUKAUSI("2004-04-10"), "tammikuu","helmi.""maaliskuu","huhtikuu.""toukokuu","kesäkuu","heinäkuu","elo."" syyskuu.""Loka.","Marras.""Joulukuu.")

Käytä sitä. :-)

29.10.2009 Vladimir
Kiitos, noin ELT(KUUKAUSI("2004-04-10"), "tam.","helmi","maaliskuu","huhtikuu.","toukokuu","kesäkuu","heinäkuu","elokuu" . ""Syys.","Loka.","Marras."
En ole kuullut.

7.10.2010 Jevgeni
Mikä toimii nopeammin? Muuntaminen pyynnössä vai PHP-toiminnon seurauksena?

10.7.2010 puolustaja
Muistia on vähintään vähemmän prosessoitavaa, vähemmän funktiokutsuja, vähemmän muistivarauksia... Käytän jotain tällaista koko ajan, mutta en mysqlissä, vaan postgresqlissä.

10.8.2010 Admin
Evgeny, puolustaja sanoi oikein, tämän muunnoksen pitäisi toimia kauniimmin tietokannan läpi, mutta tietysti jos me puhumme valtavien tietomäärien poimimisesta.
Jos vedät 10-20 tietuetta, päivämäärän muuntamisessa ei ole eroa muihin kuormiin, tämä on pikku juttu.

27.01.2011 pcemma
uhh kiitos afftorille (: ei ole enää tarvetta käyttää mega cool -toimintoani muuntamiseen (:

13.04.2011 Xes
MITEN SITÄ KÄYTETÄÄN PHP:ssä
while ($sqlr=mysql_fetch_array($sql))
{
echo ($sqlr["comadd"]." ".$sqlr["kommentti"]."

");

$sqlr["comadd"] - Pitääkö se esittää normaalissa muodossa?
}

14.4.2011 Vitali
Minulla on päivämäärä tietokannassa muodossa 19.11.2008, taulukkotyyppi VARCHAR, kuinka voin kirjoittaa sen uudelleen tietokantaan muodossa 2008-11-19?
Kädet vain todella pitkään...
Kiitos.

15.04.2011 admin
Xes, tämä on MySQL-toiminto, sinun on käytettävä sitä sql-kysely, joka koodisi perusteella sijaitsee jossain yläpuolella. Sitä ei voi käyttää tässä koodin osassa.

15.04.2011 admin
Vitaly, muuta vain solutyypiksi DATE, mysql muuntaa automaattisesti kaikki tämän solun tiedot muotoon 2008-11-19.
Mutta varmuuden vuoksi, ennen kuin muutat solutyyppiä, tee tästä taulukosta vedos, koska yhtäkkiä tietokanta tekee jotain väärin ja taulukko hajoaa kokonaan.

Jos on tärkeää jättää kenttätyypiksi varchar, aseta DATE-tyypin asettamisen jälkeen takaisin varchar...

Tämä on yksinkertaisin vaihtoehto, mutta ei täysin oikea, mutta tarkistin sen toimivan.

14.5.2011 DDD
päivämäärä("d-m-Y",strtotime("$myrow"));

24.5.2011 Konstantin
ja otan aina SELECT *,UNIX_TIMESTAMP(created) KUIN luotu FROM...
Mutta moottorilla voin tehdä sen missä tahansa muodossa. Jopa vain päivä, vaikka vain hetki...
ja vertaa kumpi on suurempi kuin 14.5.2011 vai 14.5.2010...
Ja kirjoitan sen näin:
...date=".gmdate("Y-m-d H:i:s",$created)...
ja yleensäkään en näe mitään syytä muuttaa tapoja

24.5.2011 Sergei
Konstantin, itse käytän sitä tulostukseen php päivämäärä(), tarkastelemme vain vaihtoehtoa muuttaa päivämäärä ei PHP:n, vaan mysql:n kautta.

Sanoisin, että tämä on vain yleiskatsaus mysql-funktiosta ja sillä on varmasti oikeus olemassaoloon...

Nämä toiminnot on myös suunniteltu toimimaan kalenteritietotyyppien kanssa. Katsotaanpa niitä tarkemmin.

  • DATE_FORMAT(päivämäärä, muoto) muotoilee päivämäärän valitun muodon mukaan. Tätä toimintoa käytetään hyvin usein. Esimerkiksi MySQL:ssä päivämäärämuoto on VVVV-KK-PP (vuosi-kuukausi-päivä), kun taas tunnemme paremmin muotoa PP-KK-VVVV (päivämäärä-kuukausi-vuosi). Siksi, jotta päivämäärä näkyy tavalliseen tapaan, se on muotoiltava uudelleen. Esitetään ensin kysely ja sitten selvitetään, miten muoto asetetaan:

    SELECT DATE_FORMAT(CURDATE(), "%d.%m.%Y");

    Nyt päivämäärä näyttää meille tutulta. Päivämäärän muodon määrittämiseen käytetään erityisiä tarkenteita. Mukavuuden vuoksi luettelemme ne taulukkoon.

    Defred Kuvaus
    %a Viikonpäivän lyhennetty nimi (ma - maanantai, ti - tiistai, ke - keskiviikko, to - torstai, pe - perjantai, la - lauantai, su - sunnuntai).

    Esimerkki:

    SELECT DATE_FORMAT(CURDATE(), "%a");

    Tulos:

    %b Kuukausien lyhennetyt nimet (tammi-tammikuu, helmi-helmikuu, maalis-maaliskuu, huhti-huhtikuu, touko-toukokuu, kesä-kesäkuu, heinä-heinäkuu, elo-elokuu, syys-syyskuu, loka-lokakuu, marras-marraskuu, joulukuuta - joulukuu).

    Esimerkki:

    SELECT DATE_FORMAT(CURDATE(), "%b");

    Tulos:

    %c Kuukausi numeromuodossa (1 - 12).

    Esimerkki:

    SELECT DATE_FORMAT(CURDATE(), "%s");

    Tulos:

    %d Kuukauden päivä numeromuodossa nollalla (01 - 31).

    Esimerkki:

    SELECT DATE_FORMAT(CURDATE(), "%d");

    Tulos:

    %D Kuukauden päivä englanniksi (1st, 2nd...).

    Esimerkki:

    SELECT DATE_FORMAT(CURDATE(), "%D");

    Tulos:

    %e Kuukauden päivä numeromuodossa ilman nollaa (1 - 31).

    Esimerkki:

    SELECT DATE_FORMAT(CURDATE(), "%e");

    Tulos:

    %H Tuntia etunollalla 00-23.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-15 23:03:20", "%H");

    Tulos:

    %h Kello etunollalla 00-12.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-15 23:03:20", "%h");

    Tulos:

    %i Minuutit 00-59.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-15 23:03:20", "%i");

    Tulos:

    %j Päivä vuodesta 001 - 366.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-15 23:03:20", "%j");

    Tulos:

    %k Kello etunollalla 0-23.

    Esimerkki:

    SELECT DATE_FORMAT("2011-12-31 01:03:20", "%k");

    Tulos:

    %l Kello ilman etunollaa 1-12.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-15 00:03:20", "%l");

    Tulos:

    %M

    Esimerkki:

    Tulos:

    %M Kuukauden nimi ilman lyhennettä.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-15 00:03:20", "%M");

    Tulos:

    %m Kuukausi numeromuodossa ja alussa nolla (01 - 12).

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-15 00:03:20", "%m");

    Tulos:

    %p AM tai PM 12 tunnin muodossa.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-15 00:03:20", "%p");

    Tulos:

    %r Aika 12 tunnin muodossa.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-15 00:03:20", "%r");

    Tulos:

    %s Sekunnit 00-59.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-15 00:03:20", "%s");

    Tulos:

    %T Aika 24 tunnin muodossa.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-15 21:03:20", "%T");

    Tulos:

    %u Viikko (00 - 52), jolloin viikon ensimmäinen päivä on maanantai.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-17 21:03:20", "%u");

    Tulos:

    %U Viikko (00 - 52), jolloin viikon ensimmäinen päivä on sunnuntai.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-17 21:03:20", "%U");

    Tulos:

    %W Viikonpäivän nimi ilman lyhennettä.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-17 21:03:20", "%W");

    Tulos:

    % w Viikonpäivän numero (0 - sunnuntai, 6 - lauantai).

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-17 21:03:20", "%w");

    Tulos:

    %Y Vuosi, 4 luokkaa.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-17 21:03:20", "%Y");

    Tulos:

    %y Vuosi, 2 luokkaa.

    Esimerkki:

    SELECT DATE_FORMAT("2011-04-17 21:03:20", "%y");

    Tulos:


  • STR_TO_DATE(päivämäärä, muoto) on edellisen käänteisfunktio, se ottaa päivämäärän muodossa ja palauttaa päivämäärän MySQL-muodossa.

    SELECT STR_TO_DATE("17.4.2011 23:50", "%d.%m.%Y %H:%i");



  • TIME_FORMAT(aika, muoto)-funktio on samanlainen kuin DATE_FORMAT()-funktio, mutta sitä käytetään vain ajalla:

    SELECT TIME_FORMAT("22:38:15", "%H-%i-%s");



  • GET_FORMAT(päivämäärä, muoto)-funktio palauttaa muotomerkkijonon, joka vastaa yhtä viidestä aikamuodosta:

    euroa - eurooppalainen standardi
    USA - Amerikkalainen standardi
    JIS - japanilainen teollisuusstandardi
    ISO - ISO-standardi (kansainvälinen organisaatio standardit)
    SISÄINEN - kansainvälinen standardi

    Tätä funktiota on hyvä käyttää yhdessä edellisen - DATE_FORMAT() - kanssa. Katsotaanpa esimerkkiä:

    SELECT GET_FORMAT(DATE, "EUR"), DATE_FORMAT("2011-04-17", GET_FORMAT(DATE, "EUR"));


    Kuten näet, itse GET_FORMAT()-funktio palauttaa esitysmuodon ja yhdessä DATE_FORMAT()-funktion kanssa se tuottaa päivämäärän vaaditussa muodossa. Tee omat kyselysi kaikilla viidellä standardilla ja näe ero.

No, nyt tiedät melkein kaiken päivämäärien ja aikojen käsittelystä MySQL:ssä. Tämä on erittäin hyödyllinen sinulle, kun kehität erilaisia ​​verkkosovelluksia. Jos käyttäjä esimerkiksi syöttää päivämäärän verkkosivulla olevaan lomakkeeseen hänelle tutussa muodossa, sinun ei ole vaikeaa käyttää tarvittavaa toimintoa niin, että päivämäärä tulee tietokantaan vaaditussa muodossa.

Arvot näissä muodoissa:

    Merkkijonona muodossa "VVVV-KK-PP" tai "VV-KK-PP" . Rento syntaksi on sallittu: mitä tahansa välimerkkiä voidaan käyttää erottimena päivämäärän osien välillä. Esimerkiksi "2012-12-31" , "2012/12/31" , "2012^12^31" ja "2012@12@31" ovat vastaavia.

    Merkkijonona ilman erottimia muodossa "VVVVKKPP" tai "VVKKPP" edellyttäen, että merkkijono on järkevä päivämääränä. Esimerkiksi "20070523" ja "070523" tulkitaan nimellä "2007-05-23", mutta "071332" on laiton (sillä on merkityksettömiä kuukausi- ja päiväosia) ja siitä tulee "0000-00-00".

    Numerona muodossa VVVVKKPP tai VVKKPP , kunhan numero on järkevä päivämääränä. Esimerkiksi 19830905 ja 830905 tulkitaan "1983-09-05" .

Siksi merkkijono "25/08/2012" ei ole kelvollinen MySQL-päiväkirjainaali. Sinulla on neljä vaihtoehtoa (jossain epämääräisessä paremmuusjärjestyksessä, ei lisäinformaatio vaatimuksistasi):

    Määritä päivämääränvalitsin antamaan päivämäärät tuetussa muodossa käyttämällä altField- ja altFormat-toimintoa:

    $("valitsin").datepicker(( altField: "#actualDate" altMuoto: "vvvv-kk-pp" ));

    Tai jos olet tyytyväinen siihen, että käyttäjät näkevät päivämäärän muodossa VVVV-KK-PP, aseta sen sijaan parametri dateFormat:

    $("valitsin").datepicker(( päivämäärämuoto: "vvvv-kk-pp" ));

  • $dt = \DateTime::createFromFormat("m/d/Y", $_POST["päivämäärä"]);

    ja sitten joko:

      hanki sopiva muotoiltu merkkijono:

      $päivämäärä = $dt->muoto("Y-m-d");

      hanki UNIX-aikaleima:

      $aikaleima = $dt->getTimestamp();

      joka sitten välitetään suoraan MySQL:ään FROM_UNIXTIME() :

      INSERT INTO user_date VALUES ("", "$name", FROM_UNIXTIME($timestamp))

  • Syötä merkkijono manuaalisesti kelvolliseen literaaliin:

    $osat = explode("/", $_POST["päivämäärä"]); $date = "$osat-$osat-$osat";

Varoitus

    Koodisi on alttiina SQL-injektiolle. Kannattaa todellakin käyttää valmiita lauseita, joissa annat muuttujat parametreina, joita ei arvioida SQL:lle. Jos et tiedä, mistä puhun tai kuinka korjata se, lue Bobby Tablesin tarina.

  • DATE-tyyppiä käytetään arvoille, joissa on päivämääräosa, mutta ei aikaosaa. MySQL hakee ja näyttää DATE-arvot muodossa "VVVV-KK-PP". Tuettu alue on "1000-01-01" - "9999-12-31".

    DateTime-tyyppiä käytetään arvoille, jotka sisältävät sekä päivämäärän että kellonajan. MySQL hakee ja näyttää DateTime-arvot muodossa "VVVV-KK-PP HH:MM:SS" . Tuettu alue on "1000-01-01 00:00:00" - "9999-12-31 23:59:59".

Joten kaikki kalenteritietotyypit on kuvattu yksityiskohtaisesti kohdassa ”10.3. Päivämäärä- ja aikatyypit » MySQL-opetusohjelmat. A tärkeää tietoa DBMS-tuesta aikavyöhykkeille on kuvattu osiossa “9.7. MySQL-palvelimen aikavyöhyketuki". Kaikki seuraava perustuu käsikirjan tutkimiseen. Samanaikaisesti tässä on ilmoitettu vain vivahteet, jotka koskevat valintaa yhden tai toisen tyypin hyväksi, joten tämä materiaali ei korvaa käsikirjaa millään tavalla, vaan täydentää sitä.

Alussa lyhyt kuvaus jokainen tyyppi:

  • TIMESTAMP - tietotyyppi päivämäärän ja ajan tallentamiseen. Tiedot tallennetaan "Unix-aikakauden" alkamisesta kuluneiden sekuntien lukumääränä. Arvoalue: 1970-01-01 00:00:00 - 2038-12-31 00:00:00. Vie 4 tavua.
  • YEAR - tietotyyppi vuoden tallentamiseen. Arvoalue: 1901 - 2155. Vie 1 tavun.
  • DATE on tietotyyppi päivämäärien tallentamiseen. Arvoalue: 1000-01-01 - 9999-12-31. Vie 3 tavua.
  • AIKA on tietotyyppi ajan tallentamiseen. Arvoalue: −828:59:59 - 828:59:59. Vie 3 tavua.
  • DATETIME on tietotyyppi päivämäärän ja ajan tallentamiseen. Arvoalue: 1000-01-01 00:00:00 - 9999-12-31 00:00:00. Vie 8 tavua.
Huomautus emännälle. Mielenkiintoista on, että useimmat ohjelmoijat uskovat, että "aikaleiman" käsite on Unix-aika. Itse asiassa aikaleima on merkki, joka on merkkijono, joka osoittaa päivämäärän ja/tai kellonajan, jolloin tietty tapahtuma tapahtui. Ja "Unix-aika" (Unix-aika) tai POSIX-aika on sekuntien määrä, joka on kulunut keskiyöstä 1. tammikuuta 1970 UTC. Aikaleiman käsite on laajempi kuin Unix-aika.

Kun olet analysoinut yllä esitettyjen tyyppien kuvauksen, voit tehdä melkein kaikki johtopäätökset tiettyjen tyyppien eduista ja haitoista. Kaikki on melko yksinkertaista ja ilmeistä.

Mutta ennen kuin puhun näiden tyyppien käytöstä, haluan huomauttaa, että käytännössä päivämäärän ja ajan tallentamiseen käytetään usein toista tyyppiä: kokonaislukuarvo (päivämäärän tallentamiseen - INT (4 tavua), päivämäärä ja aika - BIGINT (8) tavua)). Ero käytössä kokonaislukutyypit alkaen DATE ja DATETIME vain siinä mielessä, että dataa ei muotoilla tulostuksen aikana, ja laskelmissa, joissa on päivämäärät ja kellonajat, kokonaisluvut on muutettava sopivaan kalenterityyppiin. Lisäksi esitetyn arvon oikeellisuutta ei tarkisteta ennen tallentamista. Lajitteluominaisuudet säilyvät. Siksi on järkevää käyttää INT:tä ja BIGINTiä samoissa tapauksissa kuin DATE ja DATETIME, jotta siirrettävyys ja riippumattomuus DBMS:stä voidaan maksimoida. En näe muita etuja, jos niitä on, suosittelen ilmoittamaan ne kommenteissa.

Kalenteritietotyyppien käyttö MySQL:ssä

Aloitetaan yksinkertaisimmasta - tyypistä VUOSI. Sen ainoa etu on pieni koko - vain 1 tavu. Mutta tästä syystä on olemassa tiukka aluerajoitus hyväksyttäviä arvoja(tyyppi voi tallentaa vain 255 erilaisia ​​merkityksiä). Minun on vaikea kuvitella käytännön tilannetta, jossa vuosia voisi haluta tallentaa tiukasti välillä 1901-2155. Lisäksi SMALLINT-tyyppi (2 tavua) antaa alueen, joka riittää useimmissa tilanteissa vuoden tallentamiseen. Ja yhden tavun tallentaminen tietokantataulukon riviä kohden ei ole meidän aikanamme järkevää.

Tyypit PÄIVÄMÄÄRÄ Ja TREFFIAIKA voidaan yhdistää yhdeksi ryhmäksi. Ne tallentavat päivämäärän tai päivämäärän ja kellonajan melko laaja valikoima hyväksyttävät arvot palvelimelle asetetusta aikavyöhykkeestä riippumatta. Niiden käyttö on ehdottomasti käytännönläheistä. Mutta jos haluat tallentaa päivämäärät historiallisille tapahtumille, jotka ulottuvat yhteisen aikakauden taakse, sinun on valittava muita tietotyyppejä. Nämä tyypit ovat ihanteellisia tiettyjen tapahtumien päivämäärän tallentamiseen, jotka mahdollisesti jäävät TIMESTAMP-tyypin ulkopuolelle (syntymäpäivät, tuotteiden julkaisupäivät, presidentinvaalit, avaruusrakettien laukaisut jne.). Yksi asia, joka on pidettävä mielessä, kun käytät näitä tyyppejä, on tärkeä vivahde, mutta siitä lisää alla.

Tyyppi AIKA voidaan tallentaa ajanjaksot, joiden tarkkuutta alle 1 sekuntia ei tarvita, ja aikajaksot, jotka ovat alle 829 tuntia. Ei tähän ole enää mitään lisättävää.

Mielenkiintoisin tyyppi säilyy - AIKALEIMA. Sitä tulee harkita verrattuna DATE ja DATETIME: TIMESTAMP on myös suunniteltu tallentamaan tiettyjen tapahtumien päivämäärä ja/tai kellonaika. Tärkeä ero niiden välillä on arvoalueissa: TIMESTAMP ei tietenkään sovellu historiallisten tapahtumien (esim. syntymäpäivien) tallentamiseen, mutta soveltuu erinomaisesti ajankohtaisten (lokikirjaus, artikkelien julkaisupäivämäärät, tuotteiden lisääminen, tilausten tekeminen) tallentamiseen. ja tulevat tapahtumat lähitulevaisuudessa (uusien versioiden julkaisut, kalenterit ja aikataulut jne.).

TIMESTAMP-tyypin käytön tärkein mukavuus on, että tämän tyyppisille taulukoiden sarakkeille voit asettaa oletusarvon nykyisen ajan korvauksen muodossa sekä asettaa nykyisen ajan tietuetta päivitettäessä. Jos tarvitset näitä ominaisuuksia, on 99 %:n mahdollisuus, että TIMESTAMP on juuri se mitä tarvitset. (Katso ohjekirjasta kuinka tämä tehdään.)

Älä pelkää, että ohjelmistosi lakkaa toimimasta, kun lähestymme vuotta 2038. Ensinnäkin ennen tätä aikaa ohjelmistosi todennäköisesti yksinkertaisesti lopetetaan (erityisesti kirjoitettavien versioiden) käyttö. Toiseksi tämän päivämäärän lähestyessä MySQL-kehittäjät varmasti keksivät jotain ohjelmistosi toimivuuden säilyttämiseksi. Kaikki ratkaistaan, samoin kuin vuosi 2000-ongelma.

Joten käytämme TIMESTAMP-tyyppiä tallentaaksemme aikamme tapahtumien päivämäärät ja kellonajat, ja DATETIME ja DATE tallentaaksemme historiallisten tapahtumien tai syvän tulevaisuuden tapahtumien päivämäärät ja kellonajat.

Arvoalueet ovat tärkeä ero TIMESTAMP-, DATETIME- ja DATE-tyyppien välillä, mutta ei tärkeintä. Main että TIMESTAMP tallentaa arvon UTC-muodossa. Arvoa tallennettaessa se käännetään nykyisestä aikavyöhykkeestä UTC:ksi ja sitä luettaessa se käännetään nykyisestä aikavyöhykkeestä UTC:stä. DATETIME ja DATE tallentavat ja näyttävät aina saman ajan aikavyöhykkeistä riippumatta.

Aikavyöhykkeet on asetettu MySQL DBMS maailmanlaajuisesti tai nykyiselle yhteydelle.Jälkimmäistä voidaan käyttää toiminnan varmistamiseksi eri käyttäjiä eri aikavyöhykkeillä DBMS-tasolla. Kaikki aika-arvot tallennetaan fyysisesti UTC:ssä ja vastaanotetaan asiakkaalta ja annetaan asiakkaalle - hänen aikavyöhykkeensä arvoissa. Mutta vain käytettäessä TIMESTAMP-tietotyyppiä. DATE ja DATETIME vastaanottavat, tallentavat ja palauttavat aina saman arvon.

NOW()-funktio ja sen synonyymit palauttavat aika-arvon käyttäjän nykyisellä aikavyöhykkeellä.

Kaikki nämä olosuhteet huomioon ottaen sinun on oltava erittäin varovainen, kun muutat aikavyöhykettä yhteyden aikana palvelimeen ja käytät tyyppejä DATE ja DATETIME. Jos sinun on tallennettava päivämäärä (esimerkiksi syntymäaika), ei ole ongelmia. Syntymäaika on sama kaikilla vyöhykkeillä. Nuo. jos olet syntynyt 1. tammikuuta klo 0.00 UTC/GMT+0, niin tämä Ei tarkoittaa, että Amerikassa he juhlivat syntymäpäivääsi 31. joulukuuta. Mutta jos päätät tallentaa aika tapahtumia DATETIME-sarakkeessa, silloin ei yksinkertaisesti ole mahdollista käsitellä käyttäjien aikavyöhykkeitä DBMS-tasolla. Selitänpä esimerkillä:

Käyttäjä X toimii UTC/GMT+2-vyöhykkeellä, Y - UTC/GMT+3-vyöhykkeellä. Käyttäjien MySQL-yhteyksille asetetaan vastaava (jokaisella on oma) aikavyöhyke. Käyttäjä lähettää viestin foorumille, olemme kiinnostuneita viestin kirjoituspäivämäärästä.

Vaihtoehto 1: DATETIME. Käyttäjä X kirjoittaa viestin klo 14:00 UTC/GMT+2. Viestin "päivämäärä"-kentän arvo korvataan NOW()-funktion suorittamisen seurauksena - 14:00. Käyttäjä Y lukee viestin kirjoitusajan ja näkee saman kellon 14:00. Mutta hänen asetukseksi on asetettu UTC/GMT+3, ja hän luulee, että viesti ei kirjoitettu juuri nyt vaan tunti sitten.

Vaihtoehto 2: AIKALEIMA. Käyttäjä X kirjoittaa viestin klo 14:00 UTC/GMT+2. "Päivämäärä"-kenttä sisältää NOW()-funktion suorittamisen tuloksen - sisään tässä tapauksessa- 12:00 UTC/GMT+0. UserY lukee viestin kirjoitusajan ja vastaanottaa sen (UTC/GMT+3)(12:00 UTC/GMT+0) = 15:00 UTC/GMT+3. Kaikki käy juuri niin kuin haluamme. Ja mikä tärkeintä, se on erittäin kätevä käyttää: mukautettujen aikavyöhykkeiden tukemiseksi sinun ei tarvitse kirjoittaa mitään aikamuunnoskoodia.

Mahdollisuudet korvata nykyinen kellonaika ja työskennellä aikavyöhykkeiden kanssa TIMESTAMP-tyypissä ovat niin tehokkaita, että jos haluat tallentaa päivämäärän ilman aikaa tiettyyn lokiin, sinun tulee silti käyttää TIMESTAMPia DATE sijaan säästämättä 1 tavua erosta. heidän välillään. Tässä tapauksessa yksinkertaisesti ohita "00:00:00".

Jos et voi käyttää TIMESTAMP-toimintoa sen suhteellisen pienen arvoalueen vuoksi (yleensä 1-2 tapausta verrattuna 10-15 sivustotietokannassa), sinun on käytettävä DATETIME-toimintoa ja säädettävä sen arvoja huolellisesti oikeissa paikoissa(eli kun kirjoitat tähän kenttään, muuta päivämäärä UTC:ksi ja luettaessa - lukevan käyttäjän vyöhykkeen kellonaikaan). Jos tallennat vain päivämäärän, sillä ei todennäköisesti ole väliä, mikä aikavyöhyke sinulla on: Uusivuosi Kaikki viettävät tammikuun 1. päivää paikallisen ajan mukaan, täällä ei tarvitse kääntää mitään.

Aluksi haluan käsitellä aihetta, missä muodossa päivämäärät on parasta tallentaa tietokantaan: AIKALEIMA tai TREFFIAIKA. Tämä kysymys on esitetty ja esitetään monta kertaa foorumeilla, blogeissa jne. Mutta jotta en lähetä sinua heti hakukoneisiin, yritän yksinkertaisilla sanoilla ja näytä ero esimerkillä. Tyyppi TREFFIAIKA- tallentaa päivämäärän arvon muodossa "VVVV-KK-PP HH:MM:SS" eikä se riipu aikavyöhykkeestä. AIKALEIMA- tallentaa aikaleiman, ts. sekuntien määrä, joka on kulunut 1. tammikuuta 1970 lähtien. MySQL muuntaa nämä arvot ottaen huomioon nykyisen aikavyöhykkeen sekä tietokantaan kirjoitettaessa että siitä tulostettaessa. Mitä tämä tarkoittaa...
Olet esimerkiksi juuri lisännyt artikkelin tietokantaan, kalenterissasi on tammikuun ensimmäinen päivä 2014 ja kellossasi kello 01:00. Jos päivämääräkentässä on kirjoita DATETIME, niin kaikki sivustolla vierailevat näkevät tarkalleen tämän päivämäärän ja kellonajan asuinpaikastaan ​​riippumatta. Kaikki näyttää olevan kunnossa, mutta käyttäjä ( kutsukaamme häntä "Bill G"), joka asuu jossain New Yorkissa, tammikuun ensimmäinen päivä ei ole vielä saapunut - hänelle se on 31. joulukuuta 2013 ja kello näyttää 19:00. Hän on hieman hämmentynyt, koska... Hän ei ole vielä alkanut juhlia uutta vuotta, mutta hän kuvittelee jo "artikkelia tulevaisuudesta" ;) Tätä ei tapahdu TIMESTAMP-tyypin kanssa, koska Tulostettaessa sen aikavyöhyke otetaan huomioon.
"Kaikki on selvää!", sanot ja muutat nopeasti kaikki päivämääräkentät TIMESTAMP-tyyppisiksi, ja Bill G hengittää helpotuksesta, mutta ei kauaa. Rekisteröityessään sivustollesi Bill ilmoitti syntymäpäivänsä ja -aikansa. Matkustaa ympäri maailmaa, hän katselee aina verkkosivustoasi ja huomaa kauhuissaan, että hänen syntymäaikansa ja joskus myös päivämäärä on aina erilainen, koska... näytetään ottaen huomioon aikavyöhyke, jolla se sijaitsee Tämä hetki. Kyllä, tässä tapauksessa TIMESTAMP-tyyppi pelasi julman vitsin.
Päättelemme, että tiettyjä tehtäviä varten sinun on valittava sopiva kenttätyyppi tai ohjattava tallennusta/tulostusta halutun tuloksen mukaan.

Siirrytään yleisiin ongelmiin ja niiden ratkaisuvaihtoehtoihin. Valitse tietueet määritetyltä ajanjaksolta, esim. takana tietty ajanjakso aika.

SELECT * FROM `taulukon_nimi` WHERE `date_field` VÄLILLÄ "2014-07-05" JA "2014-07-15" ORDER BY "date_field";

Kaikki tietueet valitaan, joissa päivämääräkenttä-kentän päivämäärät ovat välillä 5.7.2014–15.7.2014, mukaan lukien määritetyt päivämäärät. Emme saa unohtaa, että oletusarvoisesti päivämäärät MySQL:ssä tallennetaan muodossa "VVVV-KK-PP HH:MM:SS" ja vastaavasti muodon maski on "%V-%m-%d %H:%i: %s" (vakio ISO). Kuinka ratkaista ongelma, jos päivämäärä ei ole tässä muodossa? Hylätään PHP-asetukset ja katsotaan kuinka tämä voidaan tehdä itse pyynnössä. Ja tällaisiin tarkoituksiin tarvitsemme toiminnon STR_TO_DATE(). Syntaksi: STR_TO_DATE(str, muoto), Missä " str" - päivämäärämerkkijono ja " muoto" on sitä vastaava muoto. Testataan:

SELECT STR_TO_DATE("31.12.2013", "%d.%m.%Y"); /* "31.12.2013" */ SELECT STR_TO_DATE("31.12.13 13:50", "%d/%m/%y %H:%i"); /* "2013-12-31 13:50:00" */

Suorituksen tulos on päivämäärä muodossa, jota käytetään oletuksena MySQL:ssä. Eli meidän ei tarvitse määrittää muotoa, jossa haluamme vastaanottaa tulostuspäivämäärän, vaan muotoa, jossa annamme käsittelypäivämäärän. Tällä menetelmällä yllä oleva merkintämme voisi näyttää jopa tältä:

SELECT * FROM `table_name` WHERE `date_field` BETWEEN STR_TO_DATE("07/05/2014", "%d.%m.%Y") AND STR_TO_DATE("15.7.2014", "%M %d,%Y" ") JÄRJESTÄ `päivämääräkenttä`;

Koska olemme käsitelleet päivämäärän muotoilua, katsotaan kuinka saada päivämäärä, kun otat näytteitä tarvitsemassamme muodossa, koska Monet ihmiset ovat paljon tottuneet näkemään "31.12.2014" tai "31.12.2014" kuin "2014-12-31". Käytä toimintoa tällaisiin tarkoituksiin PÄIVÄMÄÄRÄMUOTO(). Syntaksi: DATE_FORMAT(päivämäärä, muoto), Missä " Päivämäärä" - päivämäärämerkkijono ja " muoto" - muoto, joka muunnetaan " Päivämäärä". Toisin kuin STR_TO_DATE()-funktio, ilmoitamme itse halutun tulostusmuodon, mutta päivämäärä on määritettävä ISO-muoto, eli "VVVV-KK-PP HH:MM:SS". Tarkistamme:

SELECT DATE_FORMAT("2014-12-31", "%d.%m.%Y"); // 31.12.2014 SELECT DATE_FORMAT("2014-12-31", "%d %M %Y"); // 31. joulukuuta 2014

Jos kommunikoimme kanssasi reaaliajassa, niin tässä vaiheessa todennäköisesti seuraa heti kysymys: " Mutta kuinka näyttää kuukausi toisella kielellä: ukrainaksi, venäjäksi tai kiinaksi, loppujen lopuksi?"Se on hyvin yksinkertaista - asenna vaadittu kielialue. Ja tämä voidaan tehdä joko sisään asetustiedosto MySQL (my.cnf) tai yksinkertaisesti PHP:n pyyntö tietokantaan yhteyden muodostamisen jälkeen ja ennen pääkyselyitä:

SET lc_time_names = ru_RU; SELECT DATE_FORMAT("2014-12-31", "%d %M %Y"); // tulos: 31. joulukuuta 2014 // halutessasi voit lisätä myös "g". tai "vuosi" SELECT DATE_FORMAT("2014-12-31", "%d %M %Y year"); // tulos: 31. joulukuuta 2014

Kauneus! ;) Ja vielä muutama esimerkki pyynnöistä, joita myös usein tarvitaan, mutta jotka aiheuttavat hämmennystä aloittelijoille.

// Valitse kuluvan päivän tietueet SELECT * FROM `taulukon_nimi` WHERE `päivämääräkenttä` >= CURDATE(); // Kaikki eilisen tietueet SELECT * FROM `taulukon_nimi` WHERE `date_field` >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) AND `date_field` NOW() - INTERVAL 30 DAY; // Valitse kaikki kuluvan vuoden tietyltä kuukaudelta (esimerkiksi toukokuulta) SELECT * FROM `taulukon_nimi` WHERE YEAR(`päivämäärä_kenttä`) = YEAR(NOW()) AND MONTH(`date_field`) = 5 ; // tai toukokuulle, mutta vuonna 2009 SELECT * FROM `taulukon_nimi` WHERE YEAR(`date_field`) = 2009 AND MONTH(`date_field`) = 5;

En näe järkeä kuvailla yksityiskohtaisesti esimerkeissä käytettyjä MySQL-toimintoja, koska... ne ovat intuitiivisia ja vähintään vähän englantia osaavalle henkilölle ei ole vaikeaa ymmärtää, että esim. KUUKAUSI() palauttaa päivämäärän kuukauden, YEAR()- hänen vuosinsa ja PÄIVÄ() (tai synonyymi DAYOF MONTH()) - päivä. avainsana AIKAVÄLI- palvelee päivämäärien ja niiden muutosten aritmeettisia operaatioita.

VALITSE "2014-07-07 23:59:59" + VÄLI 1 SEKUNTI; // tulos: 2014-07-08 00:00:00 VALITSE "2014-07-07 23:59:59" + VÄLI 1 PÄIVÄ; // tulos: 2014-07-08 23:59:59 // sama asia. mutta käyttämällä DATE_ADD()-funktiota SELECT DATE_ADD("2014-07-07 23:59:59", INTERVAL 1 DAY); // 2014-07-08 23:59:59 // Jos haluat vähentää lisäämisen sijaan SELECT DATE_SUB("2014-07-07 23:59:59", INTERVAL 1 DAY); // 2014-07-06 23:59:59 // tai yksinkertaisesti VALITSE "2014-07-07 23:59:59" - VÄLI 1 PÄIVÄ; // 2014-07-06 23:59:59

Nämä eivät ole kaikki toimintoja päivämäärien kanssa työskentelemiseen, ja suosittelen sinua käymään ne läpi tiedotustarkoituksessa virallisella verkkosivustolla, jotta voit tietää niiden olemassaolosta, jos kohtaat ongelmia. epätavallinen tilanne. Mutta haluan toivoa, että tämäkin lyhyt arvostelu MySQL-toiminnot Päivämäärien käsittely tässä artikkelissa auttaa sinua navigoimaan tilanteessa ja tekemään oikean päätöksen. Jos vaikeuksia ilmenee edelleen, esitä kysymyksiä tässä aiheessa tai "Kysymyksesi" -osiossa. Selvitetään yhdessä ;)