1

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

问题1:有人知道IBM DB2/AS400“”日期吗?例如:

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

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

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

其他一些“零”日期是:

  • OLE 自动化:1899 年 12 月 30 日
  • SQL Server:1900 年 1 月 1 日
4

6 回答 6

4

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

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

此外,正如特雷西对他自己的回答所评论的那样,将日期存储在通用数字字段中是非常常见的(如果您的检索方法报告 Decimal 作为数据类型,我会猜到这一点),在这种情况下,它真的没有什么可做的无论如何都要使用 DB2 的内部日期格式。您应该知道,到目前为止,存储在 AS/400 数字字段中的最常见的日期格式如下或其变体:

  • yyyymmdd(公历,ISO 4 位数年份)
  • mmddyy(公历,美国 2 位数年份)
  • yyyyddd(所谓的儒略,4 位数的年份)
  • yyddd(所谓的儒略,2 位数的年份)
  • 年月日
  • cyymmdd(IBM 带有世纪标志的疯狂发明)

Julian 日期中的 ddd 是从年初开始的天数。IBM 疯狂日期中的 c 是 0 表示 19yy 或 1 表示 20yy。我还没有听说有人在“四百人”上存储自时代以来的日子,但也许您遇到了来自另一个平台的转换者。AS/400 的大型机传统强烈支持人类可读的日期。


1 AS/400(现在称为 IBM i)确实有自己的日期数据类型,而且这种数据类型实际上在内部确实包含一个纪元的天数。但那个时代已经过去了数千年,距离 20 世纪之交还很远,甚至还没有接近共同时代的开始。IBM 喜欢将这个天数称为Scaliger 数字,但对于大多数研究这个东西的人来说,它被称为Julian Day Number。您可能已经从我的回答的主要部分注意到,IBM 使用“儒略”一词来表示完全不同的东西(甚至与儒略历无关)。也就是说,IBM 所谓的“朱利安日期”真的是来自 ISO 8601 的序号日期

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

于 2009-07-31T02:27:05.167 回答
1

问题一:

我不知道 DB2 的开始日期是什么。无论如何,谷歌并不是很有帮助。你没有任何样本数据可以用来弄清楚吗?

更新:您确定日期存储为天数吗?我发现这个页面另有说明。

问题2:

在本例中假定 1900-01-01 作为开始日期,其中days是 AS/400 日期值。

DateTime myDate = new DateTime(1900, 1, 1).AddDays(days);
于 2009-07-16T18:56:30.290 回答
1

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

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

...


DateTime myClrDT = AS400.AddDays(days);
于 2009-07-16T18:57:45.433 回答
1

问题一:

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

问题2:

它应该很简单:

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

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

于 2009-07-17T13:39:05.350 回答
1

我只有 5 个月的 DB2 经验(在 AS400 上工作),所以我可以向您展示我们处理日期的方式。确实,我们在计算日期字段时考虑了“零”日期。在我们的系统中,“零”日期 =12/31/1971 0:00。我不知道这是否是 AS400 中的“唯一”“零”日期。在我们的系统文件中,我们使用的日期存储为从“零”日期(长度=5)开始的天数。

因此,每次我们必须从指定文件中获取日期字段时,我们都会将此字段转换为格式为:dd/mm/yyyy 或 yyyy-mm-dd(这取决于我们执行的环境)询问)。函数是:date( field +719892),其中field是我们存储日期的字段,719892是我们使用的每个未转换日期后添加的天数(看起来是x-12之间的天数/31/1971,您可以计算 x)。我会给你更多的例子:

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

结果是:date1=1972-01-15

于 2009-10-16T08:57:05.593 回答
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
于 2009-07-16T18:50:39.850 回答