netch80: (Default)
[personal profile] netch80
Цитируем 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 нужен в практической машинной реальности?

Date: 2009-11-13 08:39 pm (UTC)
From: [identity profile] dmitry-vk.livejournal.com
Unix timestamp — это не 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

Date: 2009-11-13 08:55 pm (UTC)
From: [identity profile] netch80.livejournal.com
> а изохронная метка времени.

А можно чуть понятнее? Как для усталого путника в пятницу:)

> glibc учитывает leap seconds

Интересно, это как? Вот я провёл тест напрямую через C вызовами gmtime() для указанного момента и за секунду до него, и вот вывод:

$ ./a.out 
2009-01-01T00:00:00
2008-12-31T23:59:59


Если уж поддерживается UTC, то надо её поддерживать полностью, включая и нумерацию секунд. А что толку с "inserting leap second"?

Date: 2009-11-13 10:11 pm (UTC)
From: [identity profile] dmitry-vk.livejournal.com
>Интересно, это как?

Не все тут просто, и я сам очень плохо разбираюсь в этом вопросе. Тем не менее:

$ 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
[Error: Irreparable invalid markup ('<time.h>') in entry. Owner must fix manually. Raw contents below.]

>Интересно, это как?

Не все тут просто, и я сам очень плохо разбираюсь в этом вопросе. Тем не менее:

$ 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

Date: 2009-11-13 10:24 pm (UTC)
From: [identity profile] netch80.livejournal.com
Ага, вот с right/* картина сошлась.

$ 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


Тестовый код:

#include 
[Error: Irreparable invalid markup ('<stdio.h>') in entry. Owner must fix manually. Raw contents below.]

Ага, вот с right/* картина сошлась.

<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 - вопрос интересный.

Date: 2009-11-13 10:29 pm (UTC)
From: [identity profile] netch80.livejournal.com
Вообще, я думаю, что они пошли не совсем корректным путём. Если unixtime всегда 86400 на сутки, но неровных секунд - надо было честно сказать про UT вместо UTC (какой именно - UT1, UT2 - уже пофиг) и делать корректировку реальной длины секунды, всё равно системы в мире синхронизируются по сети первичных источников NTP...

Date: 2009-11-13 10:35 pm (UTC)
From: [identity profile] dmitry-vk.livejournal.com
Да, путь не совсем корректен, но мне лично он больше нравится, чем Unix.
Секунды в UT* и Unix считаются атомными: все секунды абсолютно одинаковые по длине.
Как известно, не существует корректного способа подсчета времени. Все они компромиссные. Если секунды неровные, то нарушается синхронизация с UTC (секунды уже приняты и считаются по атомным часам). Если дни нецелые или же целые, по с переменной, то это неудобно. В любом случае, кто-то будет недоволен.

Date: 2009-11-13 10:38 pm (UTC)
From: [identity profile] dmitry-vk.livejournal.com
Да, вроде в POSIX (или в glibc, не уверен точно) можно получать время, используя различные способы подсчета времени, в зависимости от потребностей.

Date: 2009-11-13 10:47 pm (UTC)
From: [identity profile] netch80.livejournal.com
POSIX - точно нет. Если не считать хаки с подменой TZ в окружении и передёргом tzset().
glibc, насколько я видел, тоже явного интерфейса для этого не предоставляет...

Date: 2009-11-13 11:33 pm (UTC)
From: [identity profile] sla29970.livejournal.com
Pardon the English, but this may help explain why the usage of UTC is confused

http://www.ucolick.org/~sla/leapsecs/epochtime.html

Date: 2009-11-14 06:54 am (UTC)
From: [identity profile] netch80.livejournal.com
ROTFL! вот вам и universal...

Date: 2009-11-14 06:57 am (UTC)
From: [identity profile] netch80.livejournal.com
Спасибо за комментарий. Отличный пример, кстати, что часто никакое гугление не помогает само по себе выйти на правильный ответ, потому что нужно заранее себе представлять, что ищешь и как...

Date: 2009-11-13 10:51 pm (UTC)
From: [identity profile] netch80.livejournal.com
> http://en.wikipedia.org/wiki/Unix_time

Кстати, эта статья почему-то по предварительному гуглению не нашлась...

Profile

netch80: (Default)
netch80

January 2026

S M T W T F S
    1 23
45678910
11121314151617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 2nd, 2026 06:51 pm
Powered by Dreamwidth Studios