- 1 1. Nejkratší SQL pro získání aktuálního data/času v MySQL
- 1.1 1.1 Získání aktuálního data/času (základní)
- 1.2 1.2 Získání dnešního data pouze
- 1.3 1.3 Získání aktuálního času pouze
- 1.4 1.4 Získání aktuálního času v UTC (důležité)
- 1.5 1.5 Získání milisekund / mikrosekund
- 1.6 1.6 Nejlepší funkce podle použití (začněte zde, pokud si nejste jisti)
- 1.7 Klíčové body, které lidé často přehlížejí
- 2 2. Rozdíly mezi NOW() / CURRENT_TIMESTAMP / SYSDATE()
- 3 3. Změna formátu zobrazení aktuálního data/času
- 4 4. Výpočty datum/čas pomocí aktuálního času
- 4.1 4.1 Přidávání/odebírání pomocí INTERVAL
- 4.2 4.2 Získat data z posledních 24 hodin (nejčastější vzor)
- 4.3 4.3 Získat rozdíly ve dnech pomocí DATEDIFF()
- 4.4 4.4 Použít TIMESTAMPDIFF() pro hodiny/minuty/vteřiny
- 4.5 4.5 Získat začátek měsíce / konec měsíce (běžná reálná past)
- 4.6 Shrnutí častých chyb
- 4.7 Hlavní poznatky z této sekce
- 5 5. Pro dotazy v rozsahu je to bezpečnější než BETWEEN
- 6 6. DEFAULT CURRENT_TIMESTAMP a ON UPDATE (základy návrhu tabulek)
- 6.1 6.1 Automatické nastavení created_at (DEFAULT CURRENT_TIMESTAMP)
- 6.2 6.2 Automatická aktualizace updated_at (ON UPDATE)
- 6.3 6.3 DATETIME vs TIMESTAMP (důležité)
- 6.4 6.4 CURRENT_TIMESTAMP lze také použít s DATETIME
- 6.5 6.5 Pokud chcete použít NOW(): alternativa (trigger)
- 6.6 Běžné chyby v designu
- 6.7 Klíčové závěry z této sekce
- 7 7. Design časových pásem (ukládat v UTC, zobrazovat v místním čase)
- 7.1 7.1 Kontrola aktuálního časového pásma
- 7.2 7.2 Změna časového pásma pro sedání
- 7.3 7.3 Proč ukládat v UTC (princip ze skutečného světa)
- 7.4 7.4 Konverze časových pásem pomocí CONVERT_TZ()
- 7.5 7.5 Proč CONVERT_TZ() vrací NULL
- 7.6 7.6 Změna časového pásma pro celý server
- 7.7 Běžné chyby
- 7.8 Klíčové závěry z této sekce
- 8 8. Praktické příklady, které můžete použít přímo
- 8.1 8.1 Automatické vložení aktuálního času do logů
- 8.2 8.2 Aktualizace času posledního přihlášení
- 8.3 8.3 Fixace referenčního času v dávkových úlohách
- 8.4 8.4 Agregace pro dnes / včera / posledních 7 dní
- 8.5 8.5 Kontroly expirace (sessiony/tokeny)
- 8.6 8.6 Získat řádky expirující během N hodin
- 8.7 Co byste si vždy měli pamatovat
- 8.8 Klíčové poznatky z této sekce
- 9 9. Často kladené otázky (FAQ)
- 10 10. Shrnutí
1. Nejkratší SQL pro získání aktuálního data/času v MySQL
Pokud chcete získat aktuální datum/čas v MySQL, první funkce, které si musíte zapamatovat, jsou NOW() a CURRENT_TIMESTAMP. Níže jsou nejkratší SQL příklady podle použití.
1.1 Získání aktuálního data/času (základní)
SELECT NOW();
or
SELECT CURRENT_TIMESTAMP;
- Obě vrací aktuální datum/čas (YYYY-MM-DD HH:MM:SS).
- V rámci jednoho dotazu je čas pevně nastaven na „čas zahájení dotazu“.
Příklady použití
- Protokolování
- Získání časové značky vytvoření záznamu
- Získání referenčního času
Častá chyba
- Časová zóna aplikace a databáze se liší a dochází k „posunu času“. → Zkontrolujte pomocí
SELECT @@session.time_zone;
1.2 Získání dnešního data pouze
SELECT CURDATE();
- Návratový formát:
YYYY-MM-DD - Typ je DATE (pouze datum, ne datetime)
Příklady použití
- Vyhledávání „dnešních dat“
- Denní agregace
Poznámky
- Na rozdíl od
NOW()neobsahuje čas. - Pokud potřebujete čas pro rozsahové dotazy, použijte
NOW().
1.3 Získání aktuálního času pouze
SELECT CURTIME();
- Návratový formát:
HH:MM:SS - Typ je TIME (pouze čas)
Příklady použití
- Zobrazení času provedení dávky
- Výpis pouze časové části v protokolech
Častý úskalí
- Protože neobsahuje datum, nemůžete jej použít pro porovnání datetime.
1.4 Získání aktuálního času v UTC (důležité)
SELECT UTC_TIMESTAMP();
- Vrací UTC bez ohledu na časovou zónu serveru.
- Doporučeno pro globální služby.
Základní politika v reálných projektech
- Ukládat v UTC
- Při zobrazování převést na místní čas
Poznámky
- Pokud aplikace již převádí na UTC, dejte pozor na dvojí konverzi.
1.5 Získání milisekund / mikrosekund
SELECT NOW(3); -- milliseconds (3 digits after the decimal point)
SELECT NOW(6); -- microseconds (6 digits after the decimal point)
- K dispozici v MySQL 5.6.4 a novějších.
- Používá se pro vysoce přesné protokoly a auditování transakcí.
Časté nedorozumění
NOW()samotné nedokáže vrátit zlomkové sekundy.- Váš sloupec musí také specifikovat přesnost, např.
DATETIME(6).
1.6 Nejlepší funkce podle použití (začněte zde, pokud si nejste jisti)
| Use case | Recommended function |
|---|---|
| General current datetime | NOW() |
| Table default value | CURRENT_TIMESTAMP |
| Date only | CURDATE() |
| Time only | CURTIME() |
| Unified UTC management | UTC_TIMESTAMP() |
| High-precision logs | NOW(6) |
Klíčové body, které lidé často přehlížejí
NOW()aCURRENT_TIMESTAMPjsou v podstatě ekvivalentní (stejná hodnota)- V rámci jednoho dotazu je čas pevně nastaven
- Zobrazená hodnota se mění podle nastavení časové zóny
- Pro mikrosekundy musí definice sloupce specifikovat přesnost
2. Rozdíly mezi NOW() / CURRENT_TIMESTAMP / SYSDATE()
Existuje několik funkcí pro získání aktuálního času, ale nejzáhadnější částí je rozdíl mezi NOW(), CURRENT_TIMESTAMP a SYSDATE().
Pokud tomu nerozumíte správně, můžete v protokolech a zpracování transakcí narazit na neočekávané chování.
2.1 NOW() a CURRENT_TIMESTAMP jsou v podstatě ekvivalentní
SELECT NOW(), CURRENT_TIMESTAMP;
- Obě vrací aktuální datetime (hodnota DATETIME).
- V rámci jednoho dotazu je čas pevně nastaven na „čas zahájení dotazu“.
CURRENT_TIMESTAMPlze také použít se syntaxí volání funkce:SELECT CURRENT_TIMESTAMP();
Jak vybírat v reálných projektech
| Use case | Recommended |
|---|---|
| Simple retrieval | NOW() |
| Table DEFAULT / ON UPDATE | CURRENT_TIMESTAMP |
Důležité body
- Význam získané hodnoty je stejný.
- Hlavní rozdíl je v syntaxi/použití (např. povoleno v DEFAULT).
- Nejedná se o rozdíl typu (snadno se mylně interpretuje).
2.2 SYSDATE() vrací čas v „čase vyhodnocení“
SYSDATE() vypadá podobně jako NOW(), ale čas, kdy je hodnota pevně stanovena, je jiný.
SELECT NOW(), SLEEP(2), NOW();
Výsledek (příklad):
2025-02-23 14:00:00
2025-02-23 14:00:00
SELECT SYSDATE(), SLEEP(2), SYSDATE();
Výsledek (příklad):
2025-02-23 14:00:00
2025-02-23 14:00:02
Základní rozdíl
| Function | When the time is fixed |
|---|---|
NOW() | Query start time |
SYSDATE() | Evaluation time |
2.3 Poznámky k transakcím a replikaci
Protože NOW() je pevně nastaveno při zahájení dotazu, je
bezpečnější, když potřebujete konzistentní referenční čas uvnitř transakce.
Na druhou stranu, protože SYSDATE() závisí na čase provádění, může ovlivnit reprodukovatelnost v:
- Replikace
- Dávkové úlohy
- Hromadné zpracování logů
Obecné pravidlo
- Chcete pevný referenční čas →
NOW() - Potřebujete přesný okamžik pokaždé →
SYSDATE()(omezené použití)
2.4 Poznámka: CURRENT_DATE / CURRENT_TIME / LOCALTIME
MySQL také podporuje:
SELECT CURRENT_DATE;
SELECT CURRENT_TIME;
SELECT LOCALTIME;
CURRENT_DATE→ stejné jakoCURDATE()CURRENT_TIME→ stejné jakoCURTIME()LOCALTIME→ stejné jakoNOW()
Časté zmatení
- Jedná se převážně o „kosmetické rozdíly“; funkčně se téměř neliší.
- Pro bezpečnost upřednostněte čitelnost a standardizujte v rámci projektu.
Klíčové poznatky z této sekce
NOW()aCURRENT_TIMESTAMPv podstatě znamenají totéž.SYSDATE()se chová odlišně, protože je založeno na čase vyhodnocení.- Pro pevné referenční časy použijte jako výchozí
NOW(). - Použijte
CURRENT_TIMESTAMPpro DEFAULT a ON UPDATE.
3. Změna formátu zobrazení aktuálního data/času
Aktuální čas získaný pomocí NOW() se ve výchozím nastavení zobrazuje jako YYYY-MM-DD HH:MM:SS. V praxi často potřebujete například:
- Zobrazit pouze datum
- Použít
YYYY/MM/DD - Použít lokalizovaný formát (např. 23. února 2025)
- Zobrazit milisekundy
K tomu použijte DATE_FORMAT() (převod datetime na libovolný řetězcový formát).
3.1 Základní syntaxe DATE_FORMAT()
DATE_FORMAT(datetime, 'format_string')
Příklad: Převést aktuální čas na YYYY/MM/DD HH:MM
SELECT DATE_FORMAT(NOW(), '%Y/%m/%d %H:%i');
Příklad výstupu:
2025/02/23 14:35
Běžné specifikátory formátu
| Specifier | Meaning | Example |
|---|---|---|
%Y | 4-digit year | 2025 |
%m | 2-digit month | 02 |
%d | 2-digit day | 23 |
%H | Hour (24-hour) | 14 |
%i | Minutes | 35 |
%s | Seconds | 50 |
%f | Microseconds | 123456 |
Poznámky
- Některé specifikátory se liší mezi velkými a malými písmeny.
%hje 12‑hodinový čas,%Hje 24‑hodinový čas.
3.2 Běžné příklady formátů (často v praxi)
1. Oddělené lomítky
SELECT DATE_FORMAT(NOW(), '%Y/%m/%d');
2. Lokalizované (anglicky)
SELECT DATE_FORMAT(NOW(), '%b %d, %Y');
3. Bez sekund
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i');
Častý úskalí
- Protože vrací řetězec, nemůžete jej použít pro číselné výpočty.
- Pro porovnávání a vyhledávání byste měli použít původní typ DATETIME.
3.3 Extrahovat pouze část data nebo času
Můžete také získat části při zachování typu (namísto formátování na řetězec).
SELECT DATE(NOW()); -- date only (DATE type)
SELECT TIME(NOW()); -- time only (TIME type)
SELECT YEAR(NOW()); -- year only
SELECT MONTH(NOW()); -- month only
SELECT DAY(NOW()); -- day only
Doporučené použití
| Goal | Recommended |
|---|---|
| Formatting for display | DATE_FORMAT |
| Calculation / comparison | DATE() / TIME() |
3.4 Zobrazení s mikrosekundami
Když potřebujete logy s vysokou přesností:
SELECT NOW(6);
S formátováním:
SELECT DATE_FORMAT(NOW(6), '%Y-%m-%d %H:%i:%s.%f');
Důležité poznámky
- Váš sloupec musí být
DATETIME(6)neboTIMESTAMP(6), jinak se přesnost neuloží. - Není k dispozici v MySQL verzích starších než 5.6.4 (závisí na prostředí).
Časté chyby
Použití
DATE_FORMAT()ve WHERE klauzuli zabraňuje využití indexů. wp:list /wp:list- Špatný příklad:
WHERE DATE_FORMAT(created_at, '%Y-%m-%d') = '2025-02-23' - Doporučeno:
WHERE created_at >= '2025-02-23 00:00:00' AND created_at < '2025-02-24 00:00:00' - Ukládání přímo řetězce ve formátu pro zobrazení (snižuje výkon vyhledávání)
- Špatný příklad:
Klíčové poznatky z této sekce
- Použijte
DATE_FORMAT()ke změně formátů zobrazení. - Pro výpočty/porovnání zachovejte původní typ.
- Pokud potřebujete mikrosekundy, uveďte přesnost v definici sloupce.
- Používání funkcí ve WHERE klauzulích může způsobit problémy s výkonem.
4. Výpočty datum/čas pomocí aktuálního času
In MySQL je běžné počítat věci jako „N hodin později“, „N dní zpět“ nebo „posledních N dní“ na základě aktuálního času.
Nejčastějším reálným případem je „získat data z posledních 24 hodin.“
Základem aritmetiky s datumy a časy je INTERVAL (syntaxe pro přidávání/odebírání časových jednotek).
4.1 Přidávání/odebírání pomocí INTERVAL
Získat 1 hodinu později
SELECT NOW() + INTERVAL 1 HOUR;
Získat 3 dny zpět
SELECT NOW() - INTERVAL 3 DAY;
Získat 1 měsíc později
SELECT NOW() + INTERVAL 1 MONTH;
Běžné jednotky
| Unit | Meaning |
|---|---|
| SECOND | Seconds |
| MINUTE | Minutes |
| HOUR | Hours |
| DAY | Days |
| WEEK | Weeks |
| MONTH | Months |
| YEAR | Years |
Časté chyby
DAYvINTERVAL 1 DAYfunguje i v malých písmenech, ale měli byste to ve vašem týmu standardizovat.- Výpočty konce měsíce mohou být odlišné od očekávání, protože počet dní se liší (např. 31. ledna + 1 měsíc).
4.2 Získat data z posledních 24 hodin (nejčastější vzor)
SELECT *
FROM users
WHERE created_at >= NOW() - INTERVAL 1 DAY;
Význam
- Cílí na „od právě teď zpět 24 hodin.“
Poznámky
- Pokud použijete
CURDATE(), základní hodnota se stane „dnes v 00:00“, což mění význam.
Příklad (dnešní data):
SELECT *
FROM users
WHERE created_at >= CURDATE();
Pochopení rozdílu je klíčové
| Expression | Meaning |
|---|---|
NOW() - INTERVAL 1 DAY | Past 24 hours |
CURDATE() | Since today 00:00 |
4.3 Získat rozdíly ve dnech pomocí DATEDIFF()
SELECT DATEDIFF('2025-03-01', '2025-02-23');
Výsledek:
6
- Jednotka je „dny“
- Časová část je ignorována
Poznámky
- Znak se mění v závislosti na pořadí argumentů.
- Nemůžete vypočítat rozdíly v hodinách/minutách/vteřinách.
4.4 Použít TIMESTAMPDIFF() pro hodiny/minuty/vteřiny
SELECT TIMESTAMPDIFF(HOUR,
'2025-02-23 12:00:00',
'2025-02-23 18:30:00');
Výsledek:
6
Minuty
SELECT TIMESTAMPDIFF(MINUTE,
'2025-02-23 12:00:00',
'2025-02-23 12:30:00');
Sekundy
SELECT TIMESTAMPDIFF(SECOND,
'2025-02-23 12:00:00',
'2025-02-23 12:00:45');
Případy použití
- Výpočty trvání relace
- Kontroly expirace
- Rozhodování o timeoutu
4.5 Získat začátek měsíce / konec měsíce (běžná reálná past)
Získat první den tohoto měsíce:
SELECT DATE_FORMAT(NOW(), '%Y-%m-01');
První den následujícího měsíce:
SELECT DATE_FORMAT(NOW() + INTERVAL 1 MONTH, '%Y-%m-01');
Poznámky
- Konec měsíce není pevný datum.
- Pro dotazy v rozsahu je bezpečné použít „>= start AND < první den následujícího měsíce“.
Shrnutí častých chyb
- Používání
BETWEENs hodnotami jen datum a zapomínání na čas - Vypínání indexů použitím
DATE(created_at)ve WHERE podmínkách - Uvíznutí v problému „31. den“ při výpočtech měsíce
- Nesprávné pochopení rozdílu mezi
NOW()aCURDATE()
Hlavní poznatky z této sekce
INTERVALje základem aritmetiky s datumy a časy.- Posledních 24 hodin =
NOW() - INTERVAL 1 DAY. - Dny =
DATEDIFF(); menší jednotky =TIMESTAMPDIFF(). - Buďte opatrní s koncovými podmínkami při výpočtech založených na měsíci.
5. Pro dotazy v rozsahu je to bezpečnější než BETWEEN
Při vyhledávání v datech v MySQL mnoho začátečníků používá BETWEEN. Nicméně, často to vede k nechtěným výsledkům, pokud špatně zacházíte s časovými hranicemi, takže v praxi se doporučuje bezpečnější vzor.
5.1 Základy BETWEEN a úskalí
Běžný dotaz
SELECT *
FROM orders
WHERE order_date BETWEEN '2025-02-01' AND '2025-02-10';
Vypadá to v pořádku, ale interně je to ekvivalentní k:
WHERE order_date >= '2025-02-01 00:00:00'
AND order_date <= '2025-02-10 00:00:00'
Takže nezahrnuje data po 00:00 dne 10. února.
5.2 Bezpečnější vzor (doporučeno)
Doporučený vzor
SELECT *
FROM orders
WHERE order_date >= '2025-02-01 00:00:00'
AND order_date < '2025-02-11 00:00:00';
Klíčové body
- Specifikujte koncový limit jako „méně než další den v 00:00“
- Bezpečnější než
<= 23:59:59(podporuje mikrosekundy)
5.3 Správný způsob, jak získat dnešní data
Špatný příklad:
WHERE DATE(created_at) = CURDATE();
Problémy:
- Použití funkce na sloupec zneplatňuje indexy
- Může způsobit vážné zpomalení u velkých tabulek
Doporučeno:
WHERE created_at >= CURDATE()
AND created_at < CURDATE() + INTERVAL 1 DAY;
To zajišťuje:
- Indexy mohou být použity
- Rychlé vyhledávání
- Žádné problémy s hranicemi
5.4 Bezpečné vzory pro posledních 7 / 30 dní
Posledních 7 dní
WHERE created_at >= NOW() - INTERVAL 7 DAY;
Posledních 30 dní
WHERE created_at >= NOW() - INTERVAL 30 DAY;
Poznámky
CURDATE() - INTERVAL 7 DAYje založeno na „dnes 00:00“NOW() - INTERVAL 7 DAYje založeno na „aktuálním čase“- Zvolte podle požadavků
5.5 Klíčové pravidlo pro udržení efektivity indexů
Špatně:
WHERE DATE(created_at) = '2025-02-23';
Správně:
WHERE created_at >= '2025-02-23 00:00:00'
AND created_at < '2025-02-24 00:00:00';
Proč:
- Indexy fungují na „samotném sloupci“
- Použití funkce zabraňuje využití indexu (plné skenování)
Souhrn častých chyb
- Zapomenutí zahrnout čas v koncovém limitu u
BETWEEN - Chybějící mikrosekundy při použití
23:59:59 - Použití
DATE()ve WHERE podmínkách a zpomalení dotazů - Nejasnost mezi „now“ a „today 00:00“
Hlavní závěry z této sekce
- Rozsahové dotazy jsou nejbezpečnější s
>= start AND < end. BETWEENvyžaduje opatrné zacházení s hranicemi.- Aby byly indexy efektivní, neobalujte sloupce funkcemi.
- Jasně si vyberte mezi logikou založenou na
NOW()a naCURDATE().
6. DEFAULT CURRENT_TIMESTAMP a ON UPDATE (základy návrhu tabulek)
V návrhu databáze je běžné automaticky spravovat created_at a updated_at.
V MySQL CURRENT_TIMESTAMP umožňuje nastavit aktuální čas automaticky při vložení i aktualizaci.
6.1 Automatické nastavení created_at (DEFAULT CURRENT_TIMESTAMP)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Chování:
INSERT INTO users (name) VALUES ('Alice');
→ Aktuální čas je automaticky vložen do created_at.
Klíčové body
CURRENT_TIMESTAMPmůže být použito v DEFAULT.NOW()nelze použít přímo v DEFAULT.
Častá chyba
created_at DATETIME DEFAULT NOW(); -- error
Důvod:
- V MySQL obecně nelze nastavit funkci jako DEFAULT (výjimkou je CURRENT_TIMESTAMP).
6.2 Automatická aktualizace updated_at (ON UPDATE)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
);
Chování:
UPDATE users SET name = 'Bob' WHERE id = 1;
→ updated_at je automaticky aktualizováno na aktuální čas.
Případy použití
- Sledování posledního přihlášení
- Historie aktualizací
- Auditní logy
6.3 DATETIME vs TIMESTAMP (důležité)
| Type | Range | Time zone impact |
|---|---|---|
| DATETIME | Year 1000 to 9999 | No |
| TIMESTAMP | 1970 to 2038 | Yes |
Základní rozdíl
TIMESTAMPje uložen interně v UTC a při zobrazení je převeden na časové pásmo relace.DATETIMEukládá doslovnou hodnotu (bez konverze).
Pokyny
| Case | Recommended type |
|---|---|
| Log management | TIMESTAMP |
| Future dates (after 2038) | DATETIME |
| Fixed values not requiring TZ conversion | DATETIME |
6.4 CURRENT_TIMESTAMP lze také použít s DATETIME
V MySQL 5.6 a novějších můžete také specifikovat CURRENT_TIMESTAMP jako DEFAULT a ON UPDATE pro sloupce typu DATETIME.
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
Poznámky
- Starší verze MySQL mají omezení (závislé na prostředí).
- Pokud potřebujete přesnost:
DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6)
6.5 Pokud chcete použít NOW(): alternativa (trigger)
CREATE TRIGGER set_created_at
BEFORE INSERT ON logs
FOR EACH ROW
SET NEW.created_at = NOW();
Případy použití
- Složitá logika počátečních hodnot
- Podmíněné přiřazení časové značky
Poznámky
- Spouštěče jsou těžko debugovatelné.
- Vyhněte se jim, pokud nejsou nezbytné.
Běžné chyby v designu
- Přidání ON UPDATE k oběma
created_ataupdated_at - Zmatek chování DATETIME a TIMESTAMP
- Odkládání rozhodnutí o časových pásmech
Klíčové závěry z této sekce
- Používejte
CURRENT_TIMESTAMPpro DEFAULT. - Používejte
ON UPDATE CURRENT_TIMESTAMPpro sledování aktualizací. - Vyberte typy na základě chování časových pásem a problému s rokem 2038.
- Pokud potřebujete přesnost, nezapomeňte na
(6).
7. Design časových pásem (ukládat v UTC, zobrazovat v místním čase)
Při práci s aktuálním časem špatný design časových pásem způsobuje posun času a dvojitou konverzi.
V praxi je nejbezpečnější výchozí nastavení „ukládat v UTC, konvertovat do místního času pro zobrazení.“

Obrázek: Základní architektura pro ukládání UTC v MySQL a zobrazení místního času
7.1 Kontrola aktuálního časového pásma
Nejprve zkontrolujte, v jakém časovém pásmu běží MySQL.
SELECT @@global.time_zone, @@session.time_zone;
@@global.time_zone→ nastavení platné pro celý server@@session.time_zone→ nastavení aktuálního připojení/sedání- Pokud zobrazuje
SYSTEM, závisí na nastavení OS
Běžné problémy
- Produkční a vývojové servery mají různá OS časová pásma
- Aplikace konvertuje do UTC a databáze konvertuje znovu (dvojitá konverze)
7.2 Změna časového pásma pro sedání
SET time_zone = 'Asia/Tokyo';
nebo sjednotit do UTC:
SET time_zone = '+00:00';
Důležité body
- Vrátí se zpět při uzavření připojení
- Pokud používáte pooling připojení, zkontrolujte nastavení aplikace
7.3 Proč ukládat v UTC (princip ze skutečného světa)
Doporučená politika
- Ukládat data v UTC
- Konvertovat do časového pásma uživatele při zobrazení
Důvody:
- Snadnější podpora internacionalizace
- Vyhnout se problémům s letním časem (DST)
- Minimalizovat dopad při přesunu serverů
Získat UTC:
SELECT UTC_TIMESTAMP();
7.4 Konverze časových pásem pomocí CONVERT_TZ()
Příklad: UTC → JST
SELECT CONVERT_TZ('2025-02-23 05:35:00', '+00:00', '+09:00');
Použití názvů časových pásem:
SELECT CONVERT_TZ('2025-02-23 05:35:00', 'UTC', 'Asia/Tokyo');
Příklad ze skutečného světa
SELECT CONVERT_TZ(created_at, 'UTC', 'Asia/Tokyo')
FROM users;
7.5 Proč CONVERT_TZ() vrací NULL
Pokud vrací NULL, běžné příčiny zahrnují:
- Tabulky časových pásem MySQL nejsou načteny
- Zadaný název časového pásma neexistuje
Příklad načtení na Linuxu:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
Poznámky
- V produkci ověřte oprávnění a zda je vyžadován restart
- V Dockeru může zoneinfo chybět v závislosti na imagi
7.6 Změna časového pásma pro celý server
Konfigurační soubor (my.cnf / my.ini):
[mysqld]
default_time_zone = '+00:00'
Ověření po restartu:
SELECT @@global.time_zone;
Důležité
- Pro změny v produkci ověřte rozsah dopadu
- Buďte opatrní s existujícími daty (někdy se změní pouze zobrazení)
Běžné chyby
- Ukládání místního času místo UTC a pozdější přidání podpory internacionalizace
- Dvojitá konverze mezi aplikací a databází
- Design s DATETIME bez zohlednění časových pásem
- Různá nastavení TZ mezi testováním a produkcí
Klíčové závěry z této sekce
- Ukládat v UTC a konvertovat při zobrazení.
- Používejte
UTC_TIMESTAMP(). - Při používání
CONVERT_TZ()ověřte tabulky TZ. - Vždy zohledněte rozdíly v prostředích pro časová pásma.
8. Praktické příklady, které můžete použít přímo
Zde jsou konkrétní příklady SQL ukazující jak používat aktuální čas MySQL v reálném vývoji/provozu.
Jsou napsány tak, abyste je mohli přímo kopírovat a vkládat.
8.1 Automatické vložení aktuálního času do logů
Vytvoření tabulky
CREATE TABLE system_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
level VARCHAR(50),
message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Vložení logu
INSERT INTO system_logs (level, message)
VALUES ('ERROR', 'Failed to connect to the DB');
Klíčové body
created_atje vloženo automaticky- Není nutné předávat časové razítko z aplikace
- Základní návrh pro auditování a vyšetřování incidentů
Časté chyby
- Správa času jak v aplikaci, tak v DB
- Nesoulad času kvůli nejednotným časovým pásmům
8.2 Aktualizace času posledního přihlášení
Návrh tabulky
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255),
last_login TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
);
Aktualizace při přihlášení
UPDATE users
SET last_login = NOW()
WHERE id = 1;
Poznámky
ON UPDATEse spustí pouze když se sloupec změní- Některé UPDATE příkazy nemusí změnit hodnotu a tedy neaktualizují
8.3 Fixace referenčního času v dávkových úlohách
Pro dlouho běžící procesy je bezpečnější fixovat referenční čas.
SET @base_time = NOW();
SELECT *
FROM orders
WHERE created_at >= @base_time - INTERVAL 1 DAY;
Proč
- Čas se během procesu neposouvá
- Konzistence je zachována
8.4 Agregace pro dnes / včera / posledních 7 dní
Prodeje za dnešek
SELECT SUM(amount)
FROM orders
WHERE created_at >= CURDATE()
AND created_at < CURDATE() + INTERVAL 1 DAY;
Prodeje za včerejšek
SELECT SUM(amount)
FROM orders
WHERE created_at >= CURDATE() - INTERVAL 1 DAY
AND created_at < CURDATE();
Posledních 7 dní
SELECT COUNT(*)
FROM users
WHERE created_at >= NOW() - INTERVAL 7 DAY;
Důležité
- Nevkládejte funkce na sloupce ve WHERE podmínkách
- Pište podmínky, které umožní využití indexů
8.5 Kontroly expirace (sessiony/tokeny)
SELECT *
FROM sessions
WHERE expires_at > NOW();
Smazat expirující řádky
DELETE FROM sessions
WHERE expires_at <= NOW();
Časté chyby
- Používání
CURDATE()a ignorování času - Ukládání v UTC, ale porovnávání s lokálním
NOW()
8.6 Získat řádky expirující během N hodin
SELECT *
FROM coupons
WHERE expires_at <= NOW() + INTERVAL 1 HOUR;
Případy použití:
- Upozornění na expiraci
- Notifikace o expiraci
Co byste si vždy měli pamatovat
- Buďte explicitní, zda je vaším výchozím bodem „now“ nebo „today 00:00“
- Pište predikáty, které udržují efektivitu indexů
- Rozhodněte o návrhu časových pásem předem
- Nemíchejte
NOW()aUTC_TIMESTAMP()bez jasné politiky
Klíčové poznatky z této sekce
- Pro logy/audity/sledování aktualizací použijte
CURRENT_TIMESTAMP - Pro agregaci použijte bezpečný vzor
>= AND < - Pro správu sessionů porovnávejte s
NOW() - Fixujte výchozí čas, aby byl proces konzistentní
9. Často kladené otázky (FAQ)
Zde jsou běžné otázky ohledně aktuálního času v MySQL, zejména úskalí, která se objevují v praxi.
9.1 Jaký je rozdíl mezi NOW() a CURRENT_TIMESTAMP?
Závěr: význam vrácené hodnoty je stejný.
SELECT NOW(), CURRENT_TIMESTAMP;
Obě vrací aktuální datum a čas.
Hlavní rozdíl je v syntaktickém použití
CURRENT_TIMESTAMPlze použít vDEFAULTaON UPDATENOW()nelze použít přímo v DEFAULT
Poznámky
- Nejedná se o rozdíl typu
- Můžete specifikovat přesnost pomocí argumentů jako
(6)
9.2 Měli byste použít SYSDATE()?
SYSDATE() vrací čas v „čase vyhodnocení“.
SELECT SYSDATE(), SLEEP(2), SYSDATE();
Hodnota se může změnit i v rámci jedné dotazu.
Kdy jej použít
- Když potřebujete zaznamenat přesný reálný časový okamžik
Kdy se mu vyhnout
- Replikace
- Zpracování transakcí, kde je důležitá konzistence
Ve většině případů je použití NOW() dostačující.
9.3 Proč je čas posunutý?
Hlavní příčiny:
- Nastavení časové zóny serveru
- Nastavení časové zóny relace
- Dvojitá konverze s aplikací
- Automatické chování konverze typu TIMESTAMP
Zkontrolujte s:
SELECT @@global.time_zone, @@session.time_zone;
Opatření
- Ukládat v UTC jako výchozí
- Konvertovat pouze při zobrazení
- Sjednotit politiku mezi aplikací a DB
9.4 CONVERT_TZ() vrací NULL
Příčiny:
- Časové zóny tabulky nejsou načteny
- Nesprávný název časové zóny
Oprava:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
Buďte zvláště opatrní v prostředích Docker.
9.5 Posuny rozsahu s BETWEEN
Špatně:
WHERE created_at BETWEEN '2025-02-01' AND '2025-02-10';
Bezpečně:
WHERE created_at >= '2025-02-01 00:00:00'
AND created_at < '2025-02-11 00:00:00';
Důvody:
- Problém s časem koncové hranice
- Únik mikrosekund
- Efektivita indexu
9.6 Jak vybrat mezi DATETIME a TIMESTAMP?
- Mezinárodní podpora / správa UTC → TIMESTAMP
- Po roce 2038 nebo pevné datetimes → DATETIME
Rozhodněte o tom během návrhu.
9.7 Mikrosekundy nejsou ukládány
Příčina:
- Žádná přesnost není specifikována v definici sloupce
Oprava:
created_at DATETIME(6)
Klíčové závěry z této sekce
- Začněte s
NOW()aCURRENT_TIMESTAMP - Pro dotazy rozsahu použijte
>= AND < - Uložení v UTC je nejbezpečnější výchozí nastavení
- Nezapomeňte na výběr typu a přesnost
10. Shrnutí
Tento článek organizuje praktické způsoby získávání, formátování, výpočtu a správy aktuálního času v MySQL.
Nakonec zde jsou minimální esenciály, které byste měli znát pro bezpečnost.
10.1 Získání aktuálního času (základy)
- Obecné získání →
NOW() - DEFAULT tabulky / sledování aktualizací →
CURRENT_TIMESTAMP - Pouze datum →
CURDATE() - Pouze čas →
CURTIME() - UTC →
UTC_TIMESTAMP() - Vysoká přesnost →
NOW(6)
Pravidla palce
- Pokud si nejste jisti, použití
NOW()je většinou v pořádku. - Pro návrh schématu použijte
CURRENT_TIMESTAMP.
10.2 Dotazy rozsahu: „>= AND <“ je zlaté pravidlo
Bezpečný vzor:
WHERE created_at >= 'START'
AND created_at < 'END'
Proč:
- Zabraňuje ztrátě řádků na koncové hranici
- Funguje s mikrosekundami
- Udržuje indexy použitelnými
Špatný příklad
WHERE DATE(created_at) = CURDATE();
Neobalujte sloupec do funkce.
10.3 Základy aritmetiky datetime
- Přidání/odebrání →
INTERVAL - Rozdíly dnů →
DATEDIFF() - Rozdíly času →
TIMESTAMPDIFF()
Vždy mějte na paměti, zda je vaším základem „nyní“ nebo „dnes 00:00“.
10.4 Principy návrhu časových zón
- Ukládat v UTC
- Konvertovat při zobrazení
- Sjednotit politiku mezi aplikací a DB
Zkontrolujte s:
SELECT @@global.time_zone, @@session.time_zone;
10.5 Nejlepší postupy návrhu tabulek
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
- Standardní vybavení pro auditování/logování/sledování aktualizací
- Pokud potřebujete přesnost, specifikujte
(6)
4 nejdůležitější body z reálného světa
- Nezapomeňte na rozdíl mezi
NOW()aCURRENT_TIMESTAMP - Pro dotazy rozsahu použijte
>= AND < - Ukládat v UTC jako výchozí
- Rozhodněte o typech (DATETIME vs TIMESTAMP) během návrhu
Zpracování aktuálního času v MySQL je základní pro logování, agregaci prodejů, správu autentizace/sedání, dávkové úlohy a další.
Pokud budete dodržovat principy v tomto článku, vyhnete se mnoha běžným problémům, jako je posun času, chyby na hranicích a zhoršení výkonu.


