【问题标题】:Trying to convert a 7 digit julian date into MMDDYY format尝试将 7 位朱利安日期转换为 MMDDYY 格式
【发布时间】:2020-09-03 15:19:38
【问题描述】:

我正在尝试在 SQL Server 中将 7 位 julian/mainframe 日期转换为 mmddyy 格式的日历日期。 一个例子是朱利安日期 2005020,其中前 4 位数字是 2005 年,后三位是日历中的日期,所以 020 = 1 月 20 日。所以我需要在 SQL Server 中将此日期设为 012005(MMDDYY)。

我一直在使用以下查询,但在加载几条记录后一直收到错误:

SELECT DATEADD(day,CAST(RIGHT([julianDateColumn],3) as int)-,LEFT([julianDateColumn],4))

我遇到的错误:

从字符串转换日期和/或时间时转换失败。

最初我是在 Access DB 中使用“DATESERIAL”函数执行此操作的,但据我所知,与 SQL Server 中最接近的是“DATEFROMPARTS”,我尝试使用以下公式,但它也没有工作:

DATEFROMPARTS([julianDateColumn]/1000,1,[julianDateColumn] % 1000)

提前致谢!

【问题讨论】:

  • 跳过 YYMMDD,改用 YYYY-MM-DD! (我认为 050120 是 2020 年 5 月 1 日,还是 1 月 5 日?)
  • 070809@jarlh 呢?是 2009 年 8 月 7 日、2009 年 7 月 8 日、2007 年 8 月 9 日,还是 2007 年 9 月 8 日。;)
  • @Larnu,我的祖母出生于 1907 年。看起来像是当年的约会。
  • 当然,不列出 1907 年 8 月 9 日是多么愚蠢。:)

标签: sql sql-server datetime julian-date


【解决方案1】:

最简单的方法似乎是将左边作为年份,然后加上天数 (-1) 来确定日期。此外,我将直接使用date 数据类型,而不是使用MMDDYY 的格式。如果您希望它采用特定格式,那就是您的表示层。

SELECT JulianDate,
       CONVERT(date,DATEADD(DAY,RIGHT(JulianDate,3)-1,CONVERT(datetime,LEFT(JulianDate,4)))) AS ActualDate --4 int strings are iterpreted as the year, so I'm going to take advantage of that
FROM (VALUES('2005020'))V(JulianDate);

根据答案中的 cmets,看来 OP 的某些日期不符合所述格式 (yyyyddd)。因此,我们可以在此处使用日历表,然后将LEFT JOIN 用于查看您得到的错误行(以及INNER JOIN 用于获取日期)。

您可以使用以下内容创建表:

CREATE TABLE dbo.CalendarTable (CalendarDate date NOT NULL PRIMARY KEY,
                                CalenderYear AS DATEPART(YEAR, CalendarDate) PERSISTED,
                                CalenderMonth AS DATEPART(MONTH, CalendarDate) PERSISTED,
                                CalenderDay AS DATEPART(DAY, CalendarDate) PERSISTED,
                                CalenderMonthName AS DATENAME(MONTH, CalendarDate),
                                JulianDate AS DATEPART(YEAR,CalendarDate) * 1000 + DATEDIFF(DAY,DATEFROMPARTS(DATEPART(YEAR, CalendarDate),1,1),CalendarDate) + 1 PERSISTED); --Some example columns



WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
    FROM N N1, N N2, N N3, N N4, N N5, N N6),
Dates AS(
    SELECT CONVERT(date,DATEADD(DAY, T.I, '19000101')) AS CalendarDate
    FROM Tally T)
INSERT INTO dbo.CalendarTable(CalendarDate)
SELECT CalendarDate
FROM Dates
WHERE CalendarDate < '21000101';
GO

然后我们可以这样做来获取坏行:

SELECT YT.JulianDate
FROM dbo.YourTable YT
     LEFT JOIN dbo.CalendarTable CT ON YT.JulianDate = CT.JulianDate
WHERE CT.JulianDate IS NULL;

【讨论】:

  • 成功了!不幸的是,它仍然抛出“从字符串转换日期和/或时间时转换失败”的相同错误。在它加载一些记录之后。
  • 听起来你有一些无效的价值,@Roger。这就是为什么以实际日期数据类型以外的任何方式存储数据是一个糟糕的主意。我们需要更多示例数据,特别是未转换的值。
  • 似乎日历表可能是更好的解决方案,因此您也可以找到错误的日期。
  • 添加了一个日历表解决方案,您可以使用它来查找您的不良数据,@Roger。
  • 这太棒了!非常感谢!我已将其缩小到包含这些不良数据的特定库,我将在今晚晚些时候对其进行测试,看看我能找到什么,再次感谢!
【解决方案2】:

我想我会使用datefromparts()dateadd()

select dateadd(day,
               right(juliandate, 3) - 1),
               datefromparts(left(juliandate, 4), 1, 1)
              )
               

【讨论】:

    【解决方案3】:
    select Format(cast(concat(substring('2005020', 1, 4), '-', Month(cast(substring('2005020', 5, len('2005020')) as int)) ,'-', day(dateadd(day,-1,cast(substring('2005020', 5, len('2005020')) as int ) )  )) as date), 'MMddyy') 
    

    【讨论】:

      猜你喜欢
      • 2021-01-21
      • 2014-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多