C#:将AS / 400日期转换为DateTime

时间:2009-07-16 18:43:40

标签: datetime db2 ibm-midrange

DB2 AS / 400中的日期是一个整数,包含自20世纪初以来的某个天数。

问题1:有谁知道IBM DB2 / AS400“”日期? e.g:

  • 12/30/1899
  • 1899年12月31日
  • 1/1/1900

问题2:如果给定“AS / 400”日期(例如40010),您如何将其转换为CLR日期时间?

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

其他一些“零”日期是:

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

6 个答案:

答案 0 :(得分:4)

我不认为AS / 400日期在内部存储为从纪元日期 1 开始的一些天数(这是您称之为“零日期”的更常见的术语)。正如Tracy Probst所说,这绝对不是原生AS / 400物理文件中的日期字段。 2

但是,如果您使用任何提取数据的方法将其作为自纪元以来的天数提供给您,则无关紧要。理想情况下,您应该通过直接查看AS / 400或询问可能的人来了解预期日期。如果AS / 400上的日期是2009-07-30而你得到的是40022,那么你可以非常自信地说,纪元日期是1900年1月1日。如果你得到40024,那么时代是12月30日, 1899.(虽然当然最好比较一堆日期,最好是从不同年份开始,以防止可能使用朱利安日期。)

此外,正如Tracy对自己的答案所评论的那样,将日期存储在通用数字字段中非常常见(如果您的检索方法将Decimal作为数据类型报告,我会猜到这种情况),在这种情况下它确实无论如何都与DB2的内部日期格式无关。您应该知道,到目前为止,AS / 400数字字段中存储的最常见日期格式如下,或其变体:

  • yyyymmdd(格里高利,ISO 4位数年份)
  • mmddyy(格里高利,美国2位数年份)
  • yyyyddd(所谓的Julian,4位数年份)
  • yyddd(所谓的Julian,2位数年份)
  • YYMMDD
  • cyymmdd(IBM的世纪旗帜疯狂发明)

朱利安日期的ddd是从年初开始的天数。 IBM疯狂约会中的c为19yy为0或20yy为1。我还没有听说有人在“The Four Hundred”上存储了几天,但也许你遇到过来自另一个平台的转换。 AS / 400的主机遗产强烈支持人类可读的日期。


1 AS / 400(现在称为IBM i)确实有自己的日期数据类型,而这种数据类型实际上 在内部包含了几天从一个时代。但那个时代是many thousands of years in the past,而不是在20世纪之交的某个地方,甚至不在Common Era的开头附近。 IBM喜欢将这个天数称为 Scaliger编号,但对于研究这些内容的大多数人来说,它被称为 Julian Day Number 。正如您可能从我的答案的主要部分中注意到的那样,IBM使用“Julian”这个词来表示完全不同的东西(甚至与Julian calendar无关)。也就是说,IBM所谓的“朱利安日期”实际上就是ordinal date from ISO 8601

2 日期数据类型的内部格式非常低级,并且大多数对用户(包括大多数程序员)隐藏。 DSPPFM命令,表面上显示文件的“实际内容”,至少是“太晚”的一步:它报告的值已经从内部的4字节“Scaliger数”转换为人类可读的形式。

答案 1 :(得分:1)

问题1:

我不知道DB2的开始日期是什么。谷歌无论如何都不是很有帮助。你有没有可用于解决问题的样本数据?

更新:您确定日期存储为天数吗?我发现this page表示不这样做。

问题2:

假设1900-01-01为此示例中的开始日期,其中是AS / 400日期值。

DateTime myDate = new DateTime(1900, 1, 1).AddDays(days);

答案 2 :(得分:1)

我不知道1的答案。但对于2,你可以这样做:

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

...


DateTime myClrDT = AS400.AddDays(days);

答案 3 :(得分:1)

问题1:

据我所知,AS / 400 phsyical文件中没有“零日期”。如果我在其中带有时间戳字段的phsyical文件上执行DSPPFM,则该值将以yyyy-MM-ddhh.mm.ss格式存储为可读时间戳。例如:2005年2月8日上午7:06:33的“2005-08-0207.06.33”。在特定的编程语言中可以存在零日期,而这正是您需要关注的地方。 AS / 400 ODBC驱动程序在SQL_TYPE_TIMESTAMP字段中返回日期。

问题2:

应该如此简单:

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

我邀请其他C#专家使用更好的C#代码编辑响应。

答案 4 :(得分:1)

我只有5个月的DB2经验(在AS400上工作),所以我只能告诉你一些事情 关于我们处理日期的方式。确实,我们在计算日期字段时考虑了“零”日期。在我们的系统中,'零'日期= 12/31/1971 0:00。 我不知道这是否是AS400中的“唯一”'零'日期。 在我们的系统文件中,我们使用的日期存储为“零”日期(长度= 5)的天数。

因此,每次我们必须从指定的文件中获取日期字段时,我们将此字段转换为以下格式获取日期:dd / mm / yyyy或yyyy-mm-dd(它取决于环境,其中我们执行查询)。功能是: 日期(字段 +719892),其中字段是我们存储日期的字段, 719892 是我们在每个未转换后添加的天数我们使用的日期(似乎是x-12/31/1971之间的天数,你可以计算x)。 我会举几个例子:

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

结果是:date1=1972-01-15

答案 5 :(得分:0)

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