C #: конвертировать дату AS / 400 в DateTime - PullRequest
1 голос
/ 16 июля 2009

Даты в DB2 AS / 400 - это целые числа, содержащие количество дней с начала XX века.

Вопрос 1: Кто-нибудь знает дату IBM DB2 / AS400 " ноль "? e.g.:

  • 12 / 30/1899
  • 12/31/1899
  • 1/1/1900

Вопрос 2: Учитывая дату «AS / 400» (например, 40010), как можно преобразовать ее в CLR DateTime?

DateTime d = new DateTime(40010); //invalid

Некоторые другие «нулевые» даты:

  • OLE Automation: 12/30/1899
  • SQL Server: 1/1/1900

Ответы [ 6 ]

4 голосов
/ 31 июля 2009

Я не думаю, что даты AS / 400 хранятся внутри как некоторое количество дней от даты эпохи 1 (это более распространенный термин для того, что вы называете «нулевой датой»). Как сказала Трейси Пробст, это определенно НЕ то, как выглядят поля даты в физических файлах AS / 400. 2

Но это несущественно, если какой-либо метод, который вы используете для извлечения данных, дает вам количество дней с начала эпохи. В идеале вы должны выяснить, какая намеченная дата, посмотрев непосредственно на AS / 400 или спросив кого-то, кто может. Если дата в AS / 400 - 2009-07-30, а вы получаете 40022, то вы можете быть уверены, что дата эпохи - 1 января 1900 года. Если вы получаете 40024, то эпоха - 30 декабря, 1899. (Хотя, конечно, лучше сравнивать кучу дат, предпочтительно разных лет, чтобы не допустить возможного использования юлианских дат.)

Кроме того, как прокомментировал Трейси свой собственный ответ, очень часто даты хранятся в общих числовых полях (что я и предположил бы, если бы ваш метод поиска сообщал о десятичном виде как тип данных), и в этом случае это действительно в любом случае не имеет никакого отношения к внутреннему формату даты DB2. Вы должны знать, что наиболее распространенными форматами дат, хранящимися в числовых полях AS / 400, являются следующие или их варианты:

  • ггггммдд (григорианский, ISO 4-значный год)
  • ммддый (григорианский, США, двухзначный год)
  • гггддд (так называемый юлианский, четырехзначный год)
  • yyddd (так называемый юлианский, двузначный год)
  • ггммдд
  • cyymmdd (сумасшедшее изобретение IBM с вековым флагом)

Ддд в юлианских датах - это количество дней с начала года. C в сумасшедшей дате IBM 0 для 19yy или 1 для 20yy. Я не слышал ни о ком, кто хранит дни с тех пор на «Четырех сотнях», но, возможно, вы встречали новообращенного с другой платформы. Наследие мэйнфреймов в AS / 400 полностью поддерживает удобочитаемые даты.


1 AS / 400 (теперь называется IBM i) имеет свой собственный тип данных для дат, и этот тип данных на самом деле действительно состоит из нескольких дней из эпоха. Но эта эпоха составляет много тысячелетий в прошлом , не где-то на рубеже 20-го века и даже не в начале Общей Эры . IBM любит называть это число дней число Скалигера , но для большинства людей, которые изучают этот материал, оно называется номер дня Юлиана . Как вы, наверное, заметили из основной части моего ответа, IBM использует слово «юлианский» для обозначения чего-то совершенно другого (и даже не связанного с юлианским календарем ). А именно, так называемая «юлианская дата» IBM - это на самом деле порядковая дата из ISO 8601 .

2 Внутренний формат типа данных даты очень низкоуровневый и в основном скрыт от пользователя (включая большинство программистов). Команда DSPPFM, которая якобы показывает «фактическое содержимое» файла, по крайней мере, на один шаг «слишком поздняя»: сообщаемое ею значение уже преобразовано из внутреннего 4-байтового «числа Скалигера» в удобочитаемое человеком форма.

1 голос
/ 16 октября 2009

У меня всего 5 месяцев опыта работы с DB2 (работа на AS400), поэтому я просто могу вам кое-что показать о том, как мы работаем с датами. Это правда, что мы учитываем «нулевую» дату в наших вычислениях полей даты. В нашей системе «нулевая» дата = 12/31/1971 0:00. Я не знаю, является ли это «единственной» «нулевой» датой в AS400. В наших системных файлах дата, которую мы используем, хранится как количество дней с нулевой даты (длина = 5).

Таким образом, каждый раз, когда нам нужно получить поле даты из указанного файла, мы конвертируем это поле, чтобы получить дату в формате: дд / мм / гггг или гггг-мм-дд (это зависит от среды, в которой мы выполняем запрос). Функция: дата ( поле + 719892), где поле - это поле, в котором мы храним дату, а 719892 - количество дней, которое мы добавляем после каждой неконвертированной даты, которую мы используем (кажется, что это число дней между x-12/31/1971, вы можете вычислить x). Я приведу еще один пример:

select date(15+719892) as date1 from library1.file1

Результат: date1=1972-01-15

1 голос
/ 17 июля 2009

Вопрос 1:

Насколько я могу судить, в физическом файле AS / 400 нет "нулевой даты". Если я выполняю DSPPFM для физического файла с полем метки времени, значение сохраняется как читаемая метка времени в формате гггг-мм-ддчч.мм.сс Например: «2005-08-0207.06.33» от 02.08.2005 в 7:06:33. В конкретном языке программирования может быть нулевая дата, и это действительно то, на чем вам нужно сосредоточиться. Драйвер ODBC AS / 400 возвращает дату в поле SQL_TYPE_TIMESTAMP.

Вопрос 2:

Это должно быть так просто:

DateTime d = Convert.ToDateTime(reader["DateField"]);

Я приглашаю других экспертов C # отредактировать ответ с помощью лучшего кода C #.

1 голос
/ 16 июля 2009

Я не знаю ответ для 1. Но для 2, вы можете сделать что-то вроде этого:

private DateTime AS400 = new DateTime(1900, 1, 1);

...


DateTime myClrDT = AS400.AddDays(days);
1 голос
/ 16 июля 2009

Вопрос 1:

Понятия не имею, какая дата начала для DB2. Google не очень полезен в любом случае. У вас нет примеров данных, которые вы могли бы использовать, чтобы выяснить это?

Обновление: Вы уверены, что дата сохраняется в виде количества дней? Я нашел эту страницу , которая говорит об обратном.

Вопрос 2:

Предполагая 1900-01-01 в качестве даты начала в этом примере, где days - значение даты AS / 400.

DateTime myDate = new DateTime(1900, 1, 1).AddDays(days);
0 голосов
/ 16 июля 2009

У marc_s был комментарий, который путал «нулевые» даты с «минимальными» датами в SQL Server. Просто чтобы каждый мог увидеть пример:

SELECT 
   CAST(0 AS datetime) AS dateTimeZero,
   CAST(0 AS smalldatetime) AS smallDateTimeZero

dateTimeZero              smallDateTimeZero
=======================   ===================     
1900-01-01 00:00:00.000   1900-01-01 00:00:00
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...