65.9K
CodeProject 正在变化。 阅读更多。
Home

将 CYYMMDD (整数) 转换为 DB2 for iSeries 中的日期

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2011年10月7日

CPOL

4分钟阅读

viewsIcon

76337

将 7 位数字整数日期格式转换为 SQL 日期格式

引言

在 DB2 for iSeries 中,存在一种日期格式 CYYMMDD。从技术上讲,它是一个整数,因此对日期的比较对于机器来说变得更容易、更快。 这篇文章的目的是演示如何将这种 CYYMMDD 日期转换为 SQL 日期。 这是为了确保日期以用户可以理解的格式呈现,并避免在处理 Java (java.sql.Date) 等语言时出现类型不匹配。

理解问题

首先,让我们理解这种格式。C YY MM DD。我们都可以很容易地知道 YY 是年份的后两位数字,MM 是月份,DD 是日期。 那个“C”是什么? 正如你们中的一些人正确猜测的那样,它是世纪。 但什么世纪? 它是从 1900 年开始计算的世纪。 所以 1900-1999 年是 0 世纪,2000-2099 年是 1 世纪,以此类推。 例如,1991 年 12 月 31 日将被写成 '0911231'。 同样,2003 年 1 月 1 日将被写成 '1030101'。 因此,从左边开始的前三位数字加上 1900 将为您提供年份 (1900+103 = 2003)。 接下来两位数字为您提供月份。 后两位数字为您提供日期。 解决此问题的一种简单方法是对传入的 7 个字符长的字符串进行子串操作,并在将世纪年与 1900 相加之前执行必要的类型转换,然后在适当的位置插入连字符 (-),然后再将整个内容转换为 SQL DATE 格式。

注意:可以通过将日期字符串以 YYYY-MM-DD 格式传递给 DATE() 函数来完成 SQL DATE 类型转换。

一些特殊情况

但这里有一个问题。 由于存储在数据库中的值是整数,因此在进行子串操作之前,需要将其预先类型转换为 string。 好的,让我们假设我们将查询/参数中的整数类型转换为 string,然后进行子串操作。 它适用于所有情况吗? 因为在将数据保存/处理为整数时,会省略前导零,而 '0911231' 将显示为六位数 '911231'。 在这里,我们可以通过检查位数来避免这个问题。 如果是 7 位数,则对数字 (1,3)、(3,5)、(5,7) 进行子串操作。 否则,对数字 (1,2)、(2,4)、(2,6) 进行子串操作。 问题解决了? 答案是否定的! 1909 年 2 月 23 日呢? 它将显示为 '90223',一个五位数的数字。 另一个“else if”? 不!!! 如果你是一名程序员,请不要考虑单个案例并编写任何代码。 首先要理解什么是预期的,以及我们可以期望的所有可能的输入。 最佳的起点是边界条件方法。 如上所述,它是一个 7 位整数(仅正数)。 世纪从 1900 年开始计算。 因此,小于 1900 年的日期永远不会出现,即使一些笨蛋传递负值,他们也应该得到错误的结果或错误(随便!)。 最小的可能日期是 1900 年 1 月 1 日,即 '101'(请注意,如果采用并继续使用前面的方法,它只有三个数字,你最终会使用 7、6、5、4 和 3 位数的 if/else if/else,如果 Linus Torvalds 碰巧看到了你所做的事情,你进入天堂的概率是“nolla”。) 现在,可能的最大数字是 2899 年 12 月 31 日 (999+1900)。 由于该格式只允许 7 位数字,因此不能再用 CYYMMDD 格式表示其他日期。

解决方案

因此,无论输入是什么(从 101 到 9991231),我都需要日期。 好的,所以我需要世纪年(即删除最后四位数字后剩下的任何内容)。 所以只需除以 10000。 然后将其与 1900 相加。 如果是 '101',则为 0+1900=1900,如果是 '1010101',则为 101+1900=2001。(整数除法永远不会产生小数结果!) 好的,我们得到了年份。 接下来让我们来算月份。 它在中间(这里有点棘手)。 我发现 DB2 中的 MOD 函数在这里很方便。 MOD(NUMBER, 10000) 将给出最后四位数字,除以 100 将给出最后四位数字的前两位数字。 因此,月份的公式现在是 MOD(NUMBER, 10000)/100。 如果是 '101',它将是 MOD(101, 10000) = 101。 然后 101/100 = 1。 这是你的月份。 9991231 呢? MOD(9991231,10000) = 1231。 然后 1231/100 = 12。 这是你的月份。(同样,整数除法永远不会产生小数结果!) 因此,最后两位数字,即日期,现在单独处理。 再次,我们调用我们值得信赖的盟友 MODMOD(NUMBER, 100) 将为您提供日期,无论是什么情况。 我认为我可以安全地忽略提供关于 MOD 如何处理各种数字的 100 的示例。 然后我们必须在年、月和日之间放置连字符,并构造一个将被类型转换为日期的 string。 那样做有用吗?

    SELECT DATE(((NUMBER/10000)+1900)|| '-' ||
	(MOD(NUMBER,10000) /100)|| '-' ||
	MOD(NUMBER,100)) 
    FROM 
	SYSIBM.SYSDUMMY1;

其中 NUMBER 是你的 CYYMMDD 整数。 如果你经常使用它,为什么不编写你自己的自定义函数来为作为整数传递的任何 CYYMMDD 日期返回 DATE 呢?

-Shenbaga Murugan Paramasivapandian
(DB2 数据库管理员,Java/Web 开发人员,开源爱好者)

CYYMMDD (整数) 到 DB2 for iSeries 中的 DATE - CodeProject - 代码之家
© . All rights reserved.