AXForum  
Вернуться   AXForum > Блоги > Владимир Максимов
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

Оценить эту запись

TimeZone в Ax2009

Запись от Владимир Максимов размещена 29.09.2014 в 16:33
Теги ax2009, timezone

Ну, хорошо, новое правило определения TimeZone добавили. А что делает форма TimeZonePatcher? О каких таких "исправлениях" идет речь?

Для начала, надо разобраться с "физикой" процесса

При создании полей на основе базового типа данных Types::UtcDateTime физически, на уровне базы данных создаются 2 поля:

1. Поле с типом DateTime хранящее время UTC
2. Поле, имя которого совпадает с именем поля DateTime, но с добавленным окончанием "TZID".

Поле *TZID является служебным и не отображется в среде Axapta. Хотя в таблице SqlDictionary присутствуют.

Например, в таблице BatchJob есть поле OrigStartDateTime, которое видно в списке полей этой таблицы в AOT. Но, кроме того, у этой же таблицы есть поле OrigStartDateTimeTZID, которое можно увидеть только на уровне базы данных SQL. В среде Axapta оно не видно

В поле *TZID записывается идентификатор временной зоны (TZID = Time Zone IDentifier). Таким идентификатором является значение поля таблицы TimeZonesRulesData.RuleID
Таблица TimeZonesRulesData это правила, определяющие "сдвиг" в минутах, который надо добавить (или вычесть) к значению поля DateTime


Логика чтения полей DateTime выглядит так:

1. Из поля DateTime считывается значение
2. Из поля *TZID считывается идентификатор правила чтения временных зон, определяется "сдвиг" в минутах и прибавляется к значению DateTime


Исключением из этого правила являются поля CreatedDateTime и ModifiedDateTime. Им в пару не создаются поля *TZID. Т.е. при их считывании всегда используется текущее правило "сдвига" времени в минутах.

Причина, по которой возникает необходимость "патчить" данные - это тот факт, что поле *TZID заполняется один раз в момент создания записи и больше уже не изменяется на протяжении всего времени существования записи.

Это значит, что если, например, до импорта новых правил определения временных зон Вы создадите пакетное задание, плановое дата/время которого будет, скажем, 01.11.2014 01:00:00, то, после импорта новых правил будет отображаться значение 01.11.2014 02:00:00. Почему? Да потому, что поле *TZID останется без изменений и будет ссылаться на правила расчета 2011 года. Т.е. добавлять к времени UTC (то, что сохранено в базе данных в поле DateTime) 4 часа, а не 3, как должно быть по новым правилам.

Следовательно, необходимо для всех дат, которые попали в область действия новых правил определения временных зон сделать замену:

1. В поле *TZID записать код записи нового правила
2. Поле DateTime увеличить на 1 час

Зачем добавлять 1 час? Так в базе данных записано время UTC. Т.е. без сдвига на 4 часа там хранится время 31.10.2014 21:00:00. Если к этому времени добавить 3 часа по новым правилам, то получим 01.11.2014 00:00:00, вместо ожидаемого 1 часа. Вот чтобы поясное время не изменилось, время UTC и надо увеличить на 1 час

Собственно, именно этим и занимается форма TimeZonePatcher.

После открытия этой формы надо выбрать обновляемое правила из списка (этот список заполняется и обновляется при импорте файла XML) и нажать кнопку "Загрузить все затронутые поля UtcDateTime". Этот процесс займет некоторое время (несколько минут), поскольку связан с перебором всех таблиц и определения факта наличия в них полей на базе UtcDateTime.

После того, как в нижней части формы отобразится список полей таблиц, Вам надо выбрать те поля, который Вы будете обновлять и нажать кнопку "Применить исправление"

--------------------------------------------------------

Ну, вроде все хорошо? "Счаззз"... У нас же обязательно какая-нибудь проблема вылезет

Проблема заключается в том, что исправляются только те данные, которые попадают в область действия новых правил. В отношении правила 2014 года это не критично, поскольку он уже наступил. Просто импортируем файл XML с новыми правилами и запускаем форму TimeZonePatcher ДО наступления 26.10.2014 года. А вот с правилом 2015 года - есть проблема.

Если у Вас работают пакетные задания, то 01.01.2015 00:00:00 у всех них произойдет сдвиг запланированного времени исполнения на 1 час вперед. Почему? Так ведь у них по прежнему будет указан код *TZID относящийся к 2014 году. Как следствие, в январе сдвиг будет составлять 4 часа, а не 3 как необходимо.

Если для Вас сдвиг выполнени пакетных задний на 1 час не критичен, то этим можно пренебречь и выполнить запуск формы TimeZonePatcher после новогодних каникул 12 января. Если же это является проблемой, то следует поступить следующим образом:

1. В 2014 году импортируется только 1 правило, действующее с 26 октября 2014 кода и по 2153 год. Это импорт такого файла XML

PHP код:
<?xml version="1.0" encoding="UTF-8"?>
<Timezoneslist>
    <!-- Russian Standard Time new rules -->
    <Timezonedata>
        <Timezonerule>
            <ruleid>61004</ruleid>
            <tzenum>61</tzenum>
            <year>2014</year>
            <bias>-240</bias>
            <syear>0</syear>
            <smonth>10</smonth>
            <sdayofweek>0</sdayofweek>
            <sday>5</sday>
            <shour>2</shour>
            <sminute>0</sminute>
            <ssecond>0</ssecond>
            <sbias>60</sbias>
            <dyear>2153</dyear>
            <dmonth>12</dmonth>
            <ddayofweek>3</ddayofweek>
            <dday>5</dday>
            <dhour>23</dhour>
            <dminute>59</dminute>
            <dsecond>59</dsecond>
            <dbias>0</dbias>
        </Timezonerule>

    </Timezonedata>
</Timezoneslist>
Отличие от первоначального вариант - это тег <dyear>2153</dyear>. Это значит, что 26.10.1014 произойдет сдвиг на 1 час вперед, но перевод на 1 час назад произойдет только в 2153 году. Т.е. в 2015 году по прежнему будет работать сдвиг на 3 часа.


2. После наступления 2015 года в любое удобное время необходимо на уровне SQL-сервера выполнить замену

PHP код:
update TimeZonesRulesData
set DYear 
0
where TzEnum 
61 and RULEID 61004 
и в Axapta импортировать файл XML с правилом на 2015 год

PHP код:
<?xml version="1.0" encoding="UTF-8"?>
<Timezoneslist>
    <!-- Russian Standard Time new rules -->
    <Timezonedata>
        <Timezonerule>
            <ruleid>61005</ruleid>
            <tzenum>61</tzenum>
            <year>2015</year>
            <bias>-180</bias>
            <syear>0</syear>
            <smonth>0</smonth>
            <sdayofweek>0</sdayofweek>
            <sday>0</sday>
            <shour>0</shour>
            <sminute>0</sminute>
            <ssecond>0</ssecond>
            <sbias>0</sbias>
            <dyear>0</dyear>
            <dmonth>0</dmonth>
            <ddayofweek>0</ddayofweek>
            <dday>0</dday>
            <dhour>0</dhour>
            <dminute>0</dminute>
            <dsecond>0</dsecond>
            <dbias>0</dbias>
        </Timezonerule>
    </Timezonedata>
</Timezoneslist>
3. После перезагрузки AOS запустить форму TimeZonePatcher для 2015 года
Размещено в Без категории
Просмотров 54707 Комментарии 3
Всего комментариев 3

Комментарии

  1. Старый комментарий
    Спасибо за информацию.

    Жаль нельзя давать репутацию за сообщения в блогах.
    Запись от Logger размещена 30.09.2014 в 11:22 Logger is offline
  2. Старый комментарий
    Почему-то при настройках DYEAR=2153 и DDAY=5 Axapta посчитала, что 03.12 23:59:59 относится к текущему 2014 году. Соответственно, 04.12 произошел возврат к UTC+4

    Корректно определение даты будет если установить DDAY=1
    Запись от Владимир Максимов размещена 04.12.2014 в 13:50 Владимир Максимов is offline
  3. Старый комментарий
    Владимир Максимов
    Как выяснилось такая же беда с 4.12 только DDAY=1 не помогает
    Запись от d_alexe размещена 10.12.2014 в 15:20 d_alexe is offline
 


Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 22:55.