время, стой. раз-два.
Nov. 13th, 2009 07:42 pmЦитируем Posix:
===
Epoch
The time zero hours, zero minutes, zero seconds, on January 1, 1970
Coordinated Universal Time (UTC).
===
Смотрим в википедию - с 1970-го года в UTC было 24 вставных секунды (leap seconds).
Проверяем системные часы:
>>> a = (10*366+29*365)*86400
>>> a
1230768000
>>> import time
>>> time.gmtime(a)[0:6]
(2009, 1, 1, 0, 0, 0)
то есть никто не применял коррекцию по ним.
Первый вопрос - покажите мне хоть один юникс или одну Windows, чтобы честно реализовывала UTC, а не UT1 или UT2?
Второй вопрос - а нафига этот UTC нужен в практической машинной реальности?
===
Epoch
The time zero hours, zero minutes, zero seconds, on January 1, 1970
Coordinated Universal Time (UTC).
===
Смотрим в википедию - с 1970-го года в UTC было 24 вставных секунды (leap seconds).
Проверяем системные часы:
>>> a = (10*366+29*365)*86400
>>> a
1230768000
>>> import time
>>> time.gmtime(a)[0:6]
(2009, 1, 1, 0, 0, 0)
то есть никто не применял коррекцию по ним.
Первый вопрос - покажите мне хоть один юникс или одну Windows, чтобы честно реализовывала UTC, а не UT1 или UT2?
Второй вопрос - а нафига этот UTC нужен в практической машинной реальности?
no subject
Date: 2009-11-13 08:39 pm (UTC)http://jwz.livejournal.com/585295.html: But I see that all my Linux boxes just spat out this syslog:
Dec 31 15:59:59 cerebrum kernel: Clock: inserting leap second 23:59:60 UTC
glibc учитывает leap seconds
no subject
Date: 2009-11-13 08:55 pm (UTC)А можно чуть понятнее? Как для усталого путника в пятницу:)
> glibc учитывает leap seconds
Интересно, это как? Вот я провёл тест напрямую через C вызовами gmtime() для указанного момента и за секунду до него, и вот вывод:
Если уж поддерживается UTC, то надо её поддерживать полностью, включая и нумерацию секунд. А что толку с "inserting leap second"?
no subject
Date: 2009-11-13 10:11 pm (UTC)Не все тут просто, и я сам очень плохо разбираюсь в этом вопросе. Тем не менее:
$ gcc tm.c; TZ=UTC ./a.out; TZ=right/UTC ./a.out;
Fri Jan 1 00:00:22 1999
Fri Jan 1 00:00:21 1999
Fri Jan 1 00:00:00 1999
Thu Dec 31 23:59:59 1998
Fri Jan 1 00:00:00 1999
Thu Dec 31 23:59:60 1998
Thu Dec 31 23:59:39 1998
Thu Dec 31 23:59:38 1998
tm.c:
----cut here----
#include
Не все тут просто, и я сам очень плохо разбираюсь в этом вопросе. Тем не менее:
$ gcc tm.c; TZ=UTC ./a.out; TZ=right/UTC ./a.out;
Fri Jan 1 00:00:22 1999
Fri Jan 1 00:00:21 1999
Fri Jan 1 00:00:00 1999
Thu Dec 31 23:59:59 1998
Fri Jan 1 00:00:00 1999
Thu Dec 31 23:59:60 1998
Thu Dec 31 23:59:39 1998
Thu Dec 31 23:59:38 1998
tm.c:
----cut here----
#include <time.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
time_t t1 = 915148800+22;
time_t t2 = t1 - 1;
time_t t3 = 915148800;
time_t t4 = t3 - 1;
printf("%s", ctime(&t1));
printf("%s", ctime(&t2));
printf("%s", ctime(&t3));
printf("%s\n", ctime(&t4));
return 0;
}
----cut here----
>А можно чуть понятнее? Как для усталого путника в пятницу:)
Прошу прощения, оно как раз неизохронное.
Мое понимание такое:
Требования к метке времени в unix предъявляются такие:
1) за одну секунду (атомную) time_t увеличивается на 1
2) за один день time_t увеличивается на 86400
Требования сформировались до принятия UTC, поэтому они немного не соответствуют друг другу. Один из способов привести unix timestamp к UTC — это ввести точки разрыва в обычно монотонный ход времени. Т.е., в момент вставки leap second'ы unix timestamp делает скачок на секунду назад (и вперед в момент удаления секунду). При этом получается, что time_t оказывается разрывным и неоднозначным (в разные моменты времени time_t может повторяться). За этим должен следить ntpd (не уверен насчет этого).
В glibc решили это «исправить» и сделать unix timestamp таким вот:
1) за одну секунду (атомную) time_t увеличивается на 1
2) time_t увеличивается монотонно, непрерывно и не имеет разрывов (т.е., изохронно)
Зато здесь длина дня может быть 8639, 8640 или 8641 секунду. И в struct tm поле tm_sec уже не <= 59, а <= 60. Включение такого «правильного» режима делается заменой таймзоны из каталога right/ (переменная окружения TZ).
Много информации есть в википедии http://en.wikipedia.org/wiki/Unix_time .
http://www.mail-archive.com/leapsecs@rom.usno.navy.mil/msg00888.html
no subject
Date: 2009-11-13 10:24 pm (UTC)Тестовый код:
<pre>
$ env TZ=UTC ./t
1230767999 -> 2008-12-31T23:59:59
1230768000 -> 2009-01-01T00:00:00
1230768022 -> 2009-01-01T00:00:22
1230768023 -> 2009-01-01T00:00:23
1230768024 -> 2009-01-01T00:00:24
$ env TZ=right/UTC ./t
1230767999 -> 2008-12-31T23:59:36
1230768000 -> 2008-12-31T23:59:37
1230768022 -> 2008-12-31T23:59:59
1230768023 -> 2008-12-31T23:59:60
1230768024 -> 2009-01-01T00:00:00
</pre>
Тестовый код:
<pre><code>
#include <stdio.h>
#include <time.h>
void
test(time_t t)
{
struct tm *tm;
tm = localtime(&t);
printf("%11lu -> %04d-%02d-%02dT%02d:%02d:%02d\n",
(unsigned long) t,
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
}
int
main()
{
test(1230767999);
test(1230768000);
test(1230768022);
test(1230768023);
test(1230768024);
return 0;
}
</code></pre>
А что делает ntpd - вопрос интересный.
no subject
Date: 2009-11-13 10:29 pm (UTC)no subject
Date: 2009-11-13 10:35 pm (UTC)Секунды в UT* и Unix считаются атомными: все секунды абсолютно одинаковые по длине.
Как известно, не существует корректного способа подсчета времени. Все они компромиссные. Если секунды неровные, то нарушается синхронизация с UTC (секунды уже приняты и считаются по атомным часам). Если дни нецелые или же целые, по с переменной, то это неудобно. В любом случае, кто-то будет недоволен.
no subject
Date: 2009-11-13 10:38 pm (UTC)no subject
Date: 2009-11-13 10:47 pm (UTC)glibc, насколько я видел, тоже явного интерфейса для этого не предоставляет...
no subject
Date: 2009-11-13 11:33 pm (UTC)http://www.ucolick.org/~sla/leapsecs/epochtime.html
no subject
Date: 2009-11-14 06:54 am (UTC)no subject
Date: 2009-11-14 06:57 am (UTC)no subject
Date: 2009-11-13 10:51 pm (UTC)Кстати, эта статья почему-то по предварительному гуглению не нашлась...