Beberapa minggu yang lalu, di infrastruktur kami, saya menemukan kesalahan konfigurasi kecil dalam variabel lingkungan TZ
. Koreksi kesalahan ini mengganggu keseimbangan rapuh bug di alam semesta dan grafik RPS untuk salah satu proyek di grafit kami benar-benar menjadi gila. Saya akan memberi tahu Anda bagaimana saya mengejar beberapa jam selama beberapa hari.
Bagaimana semua ini dimulai
Script, yang diluncurkan dengan tangan dan bekerja dengan sempurna, membuat kesalahan ketika mulai dari cron.d. Studi dangkal log dalam teks biasa menunjukkan apa yang salah.
$ TZ='' clickhouse-client; echo exit=$?
ClickHouse client version 20.3.2.1.
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 20.3.2 revision 54433.
Poco::Exception. Code: 1000, e.code() = 0, e.displayText() = Exception: Could not determine time zone from TZ variable value: '': filesystem error: in file_size: Is a directory [/usr/share/zoneinfo] (version 20.3.2.1)
exit=232
Kesalahan dengan kami atau dalam program ini?
Apakah perilaku program itu benar atau itu bug?
Dokumentasi GNU menunjukkan bahwa ada 3 format yang mungkin untuk variabel lingkungan TZ
:
- Format tanpa DST (waktu musim panas)
std offset
. Contoh EST+5
,GMT+0
- Format dengan DST:
std offset dst [offset],start[/time],end[/time]
. Contoh EST+5EDT,M3.2.0/2,M11.1.0/2
. - Nama file deskripsi zona waktu. Dapat dimulai dengan tanda titik dua
:
. Jika karakter pertama (atau mengikuti titik dua) adalah garis miring /
, maka ini harus menjadi path absolut ke file. Jika tidak, maka /usr/share/zoneinfo/${TZ}
.
Mengapa klien ClickHouse membutuhkan pengetahuan waktu lokal?
Date
DateTime
DBMS timestamp, toDateTime('2020-02-02 20:20:20')
(, , ) UInt32
. , . TZ
, , 98% .
, ClickHouse ( Poco) , . .
, . cron.d TZ
, . . , 2020-04-15 2020-04-20 .
2020-04-22 ( ): " RPS "

, -, . .
self.now = int(datetime.datetime.utcnow().timestamp())
...
dt = datetime.datetime.strptime(time_str, time_format).utctimetuple()
timestamp = time.mktime(dt)
datetime.utcnow()
?
Return the current UTC date and time, with tzinfo
=None
.
This is like now()
, but returns the current UTC date and time, as a naive datetime
object. An aware current UTC datetime can be obtained by calling datetime.now(timezone.utc)
. See also now()
.
Warning: Because naive datetime
objects are treated by many datetime
methods as local times, it is preferred to use aware datetimes to represent times in UTC. As such, the recommended way to create an object representing the current time in UTC is by calling datetime.now(timezone.utc)
.
, UTC, tzinfo=None
datetime
. .timestamp()
UNIX time , UTC. : TZ=UTC
datetime.now().timestamp()
. , .timestamp()
, datetime.now(timezone.utc)
datetime.utctimetuple()
?
datetime.timetuple()
:
Return time.struct_time
such as returned by time.localtime()
.
datetime.utctimetuple()
:
If datetime
instance d is naive, this is the same as d.timetuple()
except that tm_isdst
is forced to 0 regardless of what d.dst()
returns. DST is never in effect for a UTC time.
If d is aware, d is normalized to UTC time, by subtracting d.utcoffset()
, and a time.struct_time
for the normalized time is returned. tm_isdst
is forced to 0.
Warning: Because naive datetime
objects are treated by many datetime
methods as local times, it is preferred to use aware datetimes to represent times in UTC; as a result, using utcfromtimetuple
may give misleading results. If you have a naive datetime
representing UTC, use datetime.replace(tzinfo=timezone.utc) to make it aware, at which point you can use datetime.timetuple().
. time.struct_time
, time.mktime()
. , python2. , . , UNIX timestamp .
Python, , .
, datetime.strptime().timestamp()
TZ
, . - , - UTC, - , . , .
, RPS :

, , . , .
, :
- ,
TZ=''
- UTC
strptime()
- UTC,
strptime()
strptime()
strptime
2020-04-24T05:31:55+02:00
python
from datetime import datetime, timezone
from time import mktime
def pprint(d: dict):
for k in d:
print("{}: {}".format(k, d[k]))
now = {'now': datetime.now(),
'utcnow': datetime.utcnow()}
now_ts = [int(now[k].timestamp()) for k in now]
now_dict = {k: [now_ts[i], now_ts[i] - now_ts[0]] for i, k in enumerate(now)}
pprint(now_dict)
print()
ts_c = 1587699115
time_format = "%Y-%m-%dT%H:%M:%S%z"
time_str = "2020-04-24T05:31:55+02:00"
timetuples = {
'timetuple': datetime.strptime(time_str, time_format).timetuple(),
'utctimetuple': datetime.strptime(time_str, time_format).utctimetuple(),
}
ts = {
'timestamp': [
int(datetime.strptime(time_str, time_format).timestamp()),
int(datetime.strptime(time_str, time_format).timestamp()) - ts_c,
],
'timetuple': [
int(mktime(timetuples['timetuple'])),
int(mktime(timetuples['timetuple'])) - ts_c,
],
'utctimetuple': [
int(mktime(timetuples['utctimetuple'])),
int(mktime(timetuples['utctimetuple'])) - ts_c,
],
}
pprint(ts)
python TZ
#!/usr/bin/env bash
for tz in '' Europe/Moscow UTC Europe/Berlin
do
date "+==TZ=${tz} %s=="
TZ=$tz python example.py
date '+++%s++' -d '2020-04-24T05:31:55+02:00'
done
TZ
. , +02:00
.
now
timestamp
. , timetuple + mktime
.
timestamp, TZ=''
==TZ='' 1587914590==
now: [1587914590, 0]
utcnow: [1587914590, 0]
timestamp: [1587699115, 0]
timetuple: [1587706315, 7200] - TZ - UTC
utctimetuple: [1587699115, 0]
++1587699115++
TZ='+03:00'
, UTC strptime()
==TZ=Europe/Moscow 1587914590==
now: [1587914590, 0]
utcnow: [1587903790, -10800] - UTC - TZ
timestamp: [1587699115, 0]
timetuple: [1587695515, -3600] - +02:00 - TZ
utctimetuple: [1587688315, -10800] - UTC - TZ
++1587699115++
TZ=UTC
, strptime()
==TZ=UTC 1587914590==
now: [1587914590, 0]
utcnow: [1587914590, 0]
timestamp: [1587699115, 0]
timetuple: [1587706315, 7200] - +02:00 - UTC
utctimetuple: [1587699115, 0]
++1587699115++
TZ='+02:00'
, strptime()
, unset TZ
==TZ=Europe/Berlin 1587914590==
now: [1587914590, 0]
utcnow: [1587907390, -7200] - UTC - TZ
timestamp: [1587699115, 0]
timetuple: [1587699115, 0]
utctimetuple: [1587695515, -3600] - UTC - TZ... DST!
++1587699115++
, .
Tikki Schellen yang luar biasa menyarankan, "Jangan luangkan waktu dengan tangan kosong." Bagi saya, dalam peringkat bahaya, jatuh pada satu baris dengan DNS. Usahakan untuk menghindarinya sedapat mungkin.
Dan pada saat yang menarik ini saya ingin tetap sehat. Cobalah untuk tetap di rumah dan jika Anda tiba-tiba merasa sangat bosan dan tidak ada hubungannya, Anda bisa bermain game dari InnoGames . Omong-omong, kami memiliki lowongan terbuka