Дата и время: о чём нужно помнить программисту

Антон Полднев, Яндекс

Яндекс

Дата и время: о чём нужно помнить программисту

Малый ШАД

Антон Полднев,
Яндекс

План

Летоисчисление

Юлианский календарь

Григорианский календарь

Переход с Юлианского

Переход с Юлианского в Англии

Переход с Юлианского в Норвегии

Секунда

Что такое секунда?

Секунда есть время, равное 9 192 631 770 периодам излучения, соответствующего переходу между двумя сверхтонкими уровнями основного состояния атома цезия-133.

XIII Генеральная конференция по мерам и весам, 1967 год

Секунда, символ с, является единицей времени; её величина устанавливается фиксацией численного значения частоты сверхтонкого расщепления основного состояния атома цезия-133 при температуре 0 К равным в точности 9 192 631 770, когда она выражена единицей СИ с−1, что эквивалентно Гц.

XXIV Генеральная конференция по мерам и весам, 2011 год

Как хранится время?

  1. UNIX-время — количество секунд, прошедшее с  (почти)
    • Если хранить в 32-битном числе (от −231 до 231 − 1), времена будут от  до  (проблема 2038 года)
    • Если хранить в 64-битном числе, переполнение случится
  2. В Windows время хранится по-разному.
    Например, FILETIME — количество сотен наносекунд (10−7 секунды) с .
    (Хранится в 64-битном типе и переполнится в 30828 году.)

Секунда

Синхронизация времени

Network Time Protocol (NTP)

Benjamin D. Esham [Public domain], via Wikimedia Commons

By US Air Force [Public domain], via Wikimedia Commons (фрагмент)

Хранение времени в NTP

Хватит ли 128 бит?

The 64 bit value for the fraction is enough to resolve the amount of time it takes a photon to pass an electron at the speed of light. The 64 bit second value is enough to provide unambiguous time representation until the universe goes dim.

David L. Mills, NTP designer

64-битного числа для дробной части достаточно для хранения времени, за которое фотон на скорости света преодолевает электрон. 64-битного числа для количества секунд хватит для однозначного представления времени до того момента, когда Вселенная погаснет.

Дэвид Миллс, разработчик NTP

Секунда

Високосная секунда

Високосная секунда: что это?

Кто вводит?

Центр ориентации Земли Международной службы вращения Земли
(Earth Orientation Center of the International Earth Rotation and reference System Service)

Изменение продолжительности суток

To authorities responsible for the measurement and distribution of time

UTC TIME STEP
on the 1st of January 2017

A positive leap second will be introduced at the end of December 2016.
The sequence of dates of the UTC second markers will be:

2016 December 31, 23h 59m 59s
2016 December 31, 23h 59m 60s
2017 January   1,  0h  0m  0s

В чём же проблема?

Високосная секунда и NTP


write_seqlock(&xtime_lock);  
switch (time_state) {
// ...
case TIME_INS:
    timekeeping_leap_insert(-1);
    time_state = TIME_OOP;
    printk(KERN_NOTICE  
        "Clock: inserting leap second "
        "23:59:60 UTC\n");
    hrtimer_add_expires_ns(&leap_timer,
                           NSEC_PER_SEC);
    res = HRTIMER_RESTART;
    break;
// ...
}
write_sequnlock(&xtime_lock);  
        

Високосная секунда и Google

http://googleblog.blogspot.co.uk/2011/09/time-technology-and-leaping-seconds.html

Часовые пояса

CIA, World Factbook [Public domain]

By Cormullion (Own work) [CC BY 3.0], via Wikimedia Commons

Часовые пояса

Часовые пояса: история

Индия Непал Бутан
до 1920 5:53:20 5:41:16 5:58:36
до 1941 5:53:20 5:40 5:58:36
до 1942 6:30 5:40 5:58:36
до 1947 5:30 5:40 5:58:36
до 1986 5:30 5:40 5:30
до 1987 5:30 5:45 5:30
сейчас 5:30 5:45 6:00

Основа: By self (Own work) [GFDL or CC BY-SA 4.0-3.0-2.5-2.0-1.0], via Wikimedia Commons

+8
+9½
+10
+8¾
+9½
+10½
+10
+11

Imagery ©2015 CNES / Astrium, Map data ©2015

By Bahnfrend (Own work) [CC BY-SA 3.0], via Wikimedia Commons (фрагмент)

By Nachoman-au (A digital photograph taken by myself.) [GFDL, CC-BY-SA-3.0 or CC BY-SA 2.5-2.0-1.0], via Wikimedia Commons (фрагмент)

By Ville Miettinen from Helsinki, Finland (View from our cottage) [CC BY 2.0], via Wikimedia Commons (фрагмент)

Как выглядят часовые пояса в Антарктиде?

Источники:
— Commonwealth of Australia (Stations in Antarctica) [CC BY]
— By Phoenix B 1of3 (Own work) [CC0], via Wikimedia Commons

Практические моменты

Летнее и зимнее время

Летнее и зимнее время: зачем?

Опять Австралия...

Часовой пояс Зимой Летом
Australia/Lord_Howe UTC+10:30 UTC+11
Antarctica/Macquarie UTC+11
Australia/Hobart, Australia/Currie,
Australia/Melbourne, Australia/Sydney
UTC+10 UTC+11
Australia/Broken_Hill, Australia/Adelaide UTC+09:30 UTC+10:30
Australia/Brisbane, Australia/Lindeman UTC+10
Australia/Darwin UTC+09:30
Australia/Perth UTC+08
Australia/Eucla UTC+08:45
Pacific/Norfolk UTC+11:30

Бывает и интереснее

Марокко переходит на летнее время, но отменяет его на время Рамадана

Смена часовых поясов

Зачем менять часовые пояса?

Чтобы лучше жить

Чтобы было удобнее

По политическим причинам

15 августа 2015 года Северная Корея перешла с UTC+9 на UTC+8:30

Японские милитаристы совершили такое непростительное преступление, как лишение Кореи её собственного времени, наряду с попытками растоптать ее историю и культуру, насчитывающие 5 тысяч лет, и уничтожить корейскую нацию

Центральное телеграфное агентство Кореи

Как вычислить текущее местное время?

tzdata — база данных
часовых поясов

Формат данных

Zone Europe/Astrakhan
3:12:12 -      LMT     1924 May
3:00   -       +03     1930 Jun 21
4:00   Russia  +04/+05 1989 Mar 26  2:00s
3:00   Russia  +03/+04 1991 Mar 31  2:00s
4:00   -       +04     1992 Mar 29  2:00s
3:00   Russia  +03/+04 2011 Mar 27  2:00s
4:00   -       +04     2014 Oct 26  2:00s
3:00   -       +03     2016 Mar 27  2:00s
4:00   -       +04

Расшифровка

$ zdump -v Europe/Astrakhan
Europe/Astrakhan -9223372036854775808 = NULL
Europe/Astrakhan -9223372036854689408 = NULL
Europe/Astrakhan Wed Apr 30 20:47:47 1924 UTC = Wed Apr 30 23:59:59 1924 LMT isdst=0 gmtoff=11532 Europe/Astrakhan Wed Apr 30 20:47:48 1924 UTC = Wed Apr 30 23:47:48 1924 +03 isdst=0 gmtoff=10800
Europe/Astrakhan Fri Jun 20 20:59:59 1930 UTC = Fri Jun 20 23:59:59 1930 +03 isdst=0 gmtoff=10800 Europe/Astrakhan Fri Jun 20 21:00:00 1930 UTC = Sat Jun 21 01:00:00 1930 +04 isdst=0 gmtoff=14400
Europe/Astrakhan Tue Mar 31 19:59:59 1981 UTC = Tue Mar 31 23:59:59 1981 +04 isdst=0 gmtoff=14400 Europe/Astrakhan Tue Mar 31 20:00:00 1981 UTC = Wed Apr  1 01:00:00 1981 +05 isdst=1 gmtoff=18000
Europe/Astrakhan Wed Sep 30 18:59:59 1981 UTC = Wed Sep 30 23:59:59 1981 +05 isdst=1 gmtoff=18000 Europe/Astrakhan Wed Sep 30 19:00:00 1981 UTC = Wed Sep 30 23:00:00 1981 +04 isdst=0 gmtoff=14400
................. 110 строк ................. Europe/Astrakhan Sat Mar 27 22:59:59 2010 UTC = Sun Mar 28 01:59:59 2010 +03 isdst=0 gmtoff=10800 Europe/Astrakhan Sat Mar 27 23:00:00 2010 UTC = Sun Mar 28 03:00:00 2010 +04 isdst=1 gmtoff=14400
Europe/Astrakhan Sat Oct 30 22:59:59 2010 UTC = Sun Oct 31 02:59:59 2010 +04 isdst=1 gmtoff=14400 Europe/Astrakhan Sat Oct 30 23:00:00 2010 UTC = Sun Oct 31 02:00:00 2010 +03 isdst=0 gmtoff=10800
Europe/Astrakhan Sat Mar 26 22:59:59 2011 UTC = Sun Mar 27 01:59:59 2011 +03 isdst=0 gmtoff=10800 Europe/Astrakhan Sat Mar 26 23:00:00 2011 UTC = Sun Mar 27 03:00:00 2011 +04 isdst=0 gmtoff=14400
Europe/Astrakhan Sat Oct 25 21:59:59 2014 UTC = Sun Oct 26 01:59:59 2014 +04 isdst=0 gmtoff=14400 Europe/Astrakhan Sat Oct 25 22:00:00 2014 UTC = Sun Oct 26 01:00:00 2014 +03 isdst=0 gmtoff=10800
Europe/Astrakhan Sat Mar 26 22:59:59 2016 UTC = Sun Mar 27 01:59:59 2016 +03 isdst=0 gmtoff=10800 Europe/Astrakhan Sat Mar 26 23:00:00 2016 UTC = Sun Mar 27 03:00:00 2016 +04 isdst=0 gmtoff=14400
Europe/Astrakhan 9223372036854689407 = NULL Europe/Astrakhan 9223372036854775807 = NULL

GNU C Library: tzfile.c


size_t lo = 0;
size_t hi = num_transitions - 1;

// Some optimizations & linear search

/* Binary search.  */
/* assert (timer >= transitions[lo] && timer < transitions[hi]); */
while (lo + 1 < hi)
{
  i = (lo + hi) / 2;
  if (timer < transitions[i])
    hi = i;
  else
    lo = i;
}
    

Комментарии в tzdata

Srednekolymsk and Zyryanka are the most populous places amongst these districts, but have very similar populations. In fact, Wikipedia currently lists them both as having 3528 people, exactly 1668 males and 1860 females each! (Yikes!)
http://en.wikipedia.org/w/?title=Srednekolymsky_District&oldid=603435276
http://en.wikipedia.org/w/?title=Verkhnekolymsky_District&oldid=594378493
Assume this is a mistake, albeit an amusing one.

Looking at censuses, the populations of the two municipalities seem to have fluctuated recently. Zyryanka was more populous than Srednekolymsk in the 1989 and 2002 censuses, but Srednekolymsk was more populous in the most recent (2010) census, 3525 to 3170. (See pages 195 and 197 of http://www.gks.ru/free_doc/new_site/perepis2010/croc/Documents/Vol1/pub-01-05.pdf in Russian.) In addition, Srednekolymsk appears to be a much older settlement and the population of Zyryanka seems to be declining.
Go with Srednekolymsk.

Случаются неожиданности

From Even Scharning (2013-10-25):

The scheduled end of DST in Libya on Friday, October 25, 2013 was cancelled yesterday

http://www.libyaherald.com/2013/10/24/correction-no-time-change-tomorrow/

Как узнать часовой пояс по геопозиции?

Программистские тонкости

Вычисляем смещение

        >>> from datetime import *
>>> from pytz import *
>>> tz = timezone('Europe/Moscow')
>>> tz.utcoffset(datetime(2015, 8, 9, 14, 0, 0))
datetime.timedelta(0, 10800)
>>> tz.utcoffset(datetime(2014, 8, 9, 14, 0, 0))
datetime.timedelta(0, 14400)

Не всё так просто

        >>> from datetime import *
>>> from pytz import *
>>> tz = timezone('Europe/Moscow')
>>> tz.utcoffset(datetime(2014, 10, 26, 1, 30, 0))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python341\lib\site-packages\pytz-2015.4-py3.4.egg\pytz\tzinfo.py", line 408, in utcoffset
  File "C:\Python341\lib\site-packages\pytz-2015.4-py3.4.egg\pytz\tzinfo.py", line 349, in localize
pytz.exceptions.AmbiguousTimeError: 2014-10-26 01:30:00

И ещё...

        >>> tz.utcoffset(datetime(2011, 3, 27, 0, 0, 0))
datetime.timedelta(0, 10800)
>>> tz.utcoffset(datetime(2011, 3, 27, 10, 0, 0))
datetime.timedelta(0, 14400)
>>> tz.utcoffset(datetime(2011, 3, 27, 2, 30, 0))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python341\lib\site-packages\pytz-2015.4-py3.4.egg\pytz\tzinfo.py", line 408, in utcoffset
  File "C:\Python341\lib\site-packages\pytz-2015.4-py3.4.egg\pytz\tzinfo.py", line 327, in localize
pytz.exceptions.NonExistentTimeError: 2011-03-27 02:30:00

Итоги

Делаем выводы

Итоги

Спасибо за внимание!