TimeZone в Ax2009
			Запись от Владимир Максимов размещена 29.09.2014 в 16:33
			
		
		
			
			
		
		
		Ну, хорошо, новое правило определения 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
	
		
Отличие от первоначального вариант - это тег <dyear>2153</dyear>. Это значит, что 26.10.1014 произойдет сдвиг на 1 час вперед, но перевод на 1 час назад произойдет только в 2153 году. Т.е. в 2015 году по прежнему будет работать сдвиг на 3 часа.
2. После наступления 2015 года в любое удобное время необходимо на уровне SQL-сервера выполнить замену
	
		
и в Axapta импортировать файл XML с правилом на 2015 год
	
		
3. После перезагрузки AOS запустить форму TimeZonePatcher для 2015 года
		
	Для начала, надо разобраться с "физикой" процесса

При создании полей на основе базового типа данных 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>
		
	2. После наступления 2015 года в любое удобное время необходимо на уровне SQL-сервера выполнить замену
PHP код:
	
			
update TimeZonesRulesData
set DYear = 0
where TzEnum = 61 and RULEID = 61004 
		
	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
	
	Комментарии
- 
	 Спасибо за информацию. Спасибо за информацию.
 
 Жаль нельзя давать репутацию за сообщения в блогах.Запись от Logger размещена 30.09.2014 в 11:22   
- 
	 Почему-то при настройках DYEAR=2153 и DDAY=5 Axapta посчитала, что 03.12 23:59:59 относится к текущему 2014 году. Соответственно, 04.12 произошел возврат к UTC+4 Почему-то при настройках DYEAR=2153 и DDAY=5 Axapta посчитала, что 03.12 23:59:59 относится к текущему 2014 году. Соответственно, 04.12 произошел возврат к UTC+4
 
 Корректно определение даты будет если установить DDAY=1Запись от Владимир Максимов размещена 04.12.2014 в 13:50   
- 
	 Владимир Максимов Владимир Максимов
 Как выяснилось такая же беда с 4.12 только DDAY=1 не помогает Запись от d_alexe размещена 10.12.2014 в 15:20   




 
					
				
				
		
