Эффективный алгоритм определения даты в DST - PullRequest
4 голосов
/ 16 декабря 2009

Я ищу алгоритм лучше, чем O (n), чтобы определить, будет ли на дату в будущем применено летнее время (и сколько). Учитывая год, месяц, день, час, минуту и ​​часовой пояс (и копию базы данных часового пояса Олсена), как эффективно определить, будет ли эта дата в летнее время? Я ищу алгоритм, а не библиотечную функцию для вызова.

Спасибо.

ДОПОЛНИТЕЛЬНОЕ ОБЪЯСНЕНИЕ: библиотека дат, которую я использую, работает очень медленно, когда вы создаете объект с датой в будущем и часовым поясом. Оказывается, что он делает линейный расчет, чтобы вычислить дату перехода на летнее время. Мало того, это делает это во время создания объекта. Очевидно, что он может подождать, пока его не спросят, но он также должен быть более эффективным.

Конечно, правила DST изменяются, и библиотека дат не может предсказать будущее, но альтернативой является установление произвольного верхнего предела для локализованных дат.

Ответы [ 4 ]

1 голос
/ 18 декабря 2009

Все уже прокомментировали проблемы с постоянно меняющимися ТЛЧ. Но я могу принять предпосылку, что мы просто притворяемся, что известные в настоящее время правила будут действовать вечно.

Чтобы получить информацию о летнем времени, первым делом нужно рассчитать год / месяц / день для вашей будущей даты (если она еще не указана в этой форме). Затем вы ищите свой часовой пояс и вытаскиваете вариацию против UTC, правило включения / выключения летнего времени и смещение. Может быть несколько разных правил, в зависимости от того, в каком году вы хотите выбрать правильное для своего «целевого» года. По причинам, изложенным ниже, может быть полезно знать правила предыдущего года.

Правила включения / выключения будут иметь забавную спецификацию, например «Oct lastSun»: это означает, что переключение происходит ночью последнего воскресенья октября.

То, что вам нужно сделать, это собрать все эти кратко отформатированные «правила» и разработать для каждого кусочек кода, чтобы определить последнюю дату, указанную этим правилом . Сейчас декабрь, поэтому, учитывая несколько правил, таких как «Mar lastSun» и «Oct lastSun» для моего часового пояса, эти даты будут 29 марта 2009 г. и 25 октября 2009 г. Какие из этих дат более поздние? Октябрь. Октябрь связан с отключением, поэтому в настоящее время у нас НЕТ летнего времени.

Вы можете рассчитать даты включения / выключения летнего времени для текущего (т.е. целевого) года независимо от того, является ли целевая дата до или после этих дат; если дата включения / выключения наступает в будущем вашей целевой даты, просто повторите расчет правила для предыдущего года. Обратите внимание, что правила могли измениться в течение интервала, поэтому обязательно применяйте правильное правило для года, который вы просматриваете.

Наихудший случай для этого расчета, вы должны повторить два вычисления вашего правила за предыдущий год. Но в противном случае поиск не ведется, так что это строго O (1).

Я нашел калькулятор Local / DST / Tz здесь: http://home -4.tiscali.nl / ~ t876506 / WhatDay.html и, поскольку это апплет JavaScript, вы должны иметь возможность просто зашифровать код. Однако он не обрабатывает все правила, поэтому вам нужно будет добавить код для оставшихся правил.


Обновление: Я только что заметил, что у вас есть час и минута. Это немного усложняет ситуацию. Если ваша дата не соответствует дате «переключения», то приведенные выше инструкции помогут вам. В противном случае вам нужно учитывать время. Я думаю, что самое чистое, что нужно сделать, - это включить время в ваше определение «самых последних». То есть если ваше целевое время - 00:30 UTC, а время переключения для данной зоны - 01:00, тогда время переключения целевого года все еще в будущем, и вместо этого вам придется использовать время переключения предыдущего года. В практических целях это будет означать, что «другое» время переключения было самым последним, и применяется его состояние включения / выключения.

0 голосов
/ 18 декабря 2009

Хм, как я вижу, проблемным моментом является определение дня недели для данного дня в далеком будущем.

Для этого я предлагаю нечто подобное:

  • через каждые 400 лет вся система поворачивается, поэтому сначала разделите число лет на 400, примите неотъемлемую часть. Через 400 лет есть 99 високосных и 301 простых. Если произвольным днем ​​является понедельник, то в этот же день через 400 лет будет 301 + 2x99 = 499 (mod 7) ---> Понедельник + 2 ---> Среда. Итак, вы должны сказать что-то вроде этого:

wday = (ref_day + 2 * (int)((target_year - ref_year) / 400)) mod 7

  • тогда вы можете проводить дальнейшую оптимизацию, но я думаю, что вы можете ездить из года в год, что будет делать это. Самое большее, вы делаете 399 простых операций, если (leap_year), то ++ else + = 2, mod 7.

После того, как у вас будет рабочий день на 1 января того года, вы можете рассчитать даты перехода на летнее время, как писал Карл Смотриц.

0 голосов
/ 16 декабря 2009

Насколько я знаю, изменения летнего времени, которые известны, начинаются и заканчиваются в определенный день в году (первые выходные апреля, последние выходные октября, и тому подобное). Таким образом, вы можете использовать Алгоритм Судного дня , чтобы найти дни недели для данного года и рассчитать даты конвертации по ним. Затем вы можете определить, действует ли DST в исходной и / или целевой локали. Сама подготовка - это просто вопрос сложения и / или вычитания часа, чтобы компенсировать летнее время, а затем учитывать разницу во времени.

0 голосов
/ 16 декабря 2009

Ваша проблема номер один - это правила летнего времени, установленные местными властями. Последний может принять практически любой закон в любое время и, следовательно, изменить правила так, как вы не можете его предсказать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...