2

我正在尝试转换JDE 日期,并积累了大量信息,并认为我会尝试执行 SQL 转换函数来简化一些任务。

这是我想出的函数,我简称为“ToGregorian”

CREATE FUNCTION [dbo].[ToGregorian](@julian varchar(6))
RETURNS datetime AS BEGIN
    DECLARE @datetime datetime

    SET @datetime = CAST(19+CAST(SUBSTRING(@julian, 1, 1) as int) as varchar(4))+SUBSTRING(@julian, 2,2)+'-01-01'
    SET @datetime = DATEADD(day, CAST(SUBSTRING(@julian, 4,3) as int)-1, @datetime)

    RETURN @datetime
END
  1. 采用“朱利安”字符串。
  2. 取第一个字母并将其添加到世纪,从 19 日开始。
  3. 从接下来的 2 个字符开始添加十年和年。
  4. 最后添加天数,即最后 3 个字符,并减去 1,因为它在第一个设置中已经有 1 天。(例如 2011-01-01)
  5. 结果前:111186=>2011-07-05 00:00:00.000

在我看来,这有点笨拙和矫枉过正,我希望有更好的方法来做到这一点。也许我进行了太多转换,或者我应该一起使用不同的方法?

任何建议如何改进功能?
也许是一种不同的、更好的方法?
不介意它是否也可以更具可读性...

我还有一个内联版本,例如,如果我只有读取权限并且不能使用函数,这看起来也很乱,是否可以使它更具可读性或更好?

CAST(REPLACE(Convert(VARCHAR, DATEADD(d,CAST(SUBSTRING(CAST([column] AS VARCHAR), 4,3) AS INT)-1, CAST(CAST(19+CAST(SUBSTRING(CAST([column] AS VARCHAR), 1,1) AS INT) AS VARCHAR)+SUBSTRING(CAST([column] AS VARCHAR), 2,2) + '-01-01' AS DATETIME)), 111), '/', '-') AS DATETIME)
4

5 回答 5

4

我认为使用本机日期时间数学比所有这些来回切换到各种字符串、日期和数字格式更有效。

DECLARE @julian VARCHAR(6) = '111186';

SELECT DATEADD(YEAR, 
  100*CONVERT(INT, LEFT(@julian,1))
  +10*CONVERT(INT, SUBSTRING(@julian, 2,1))
  +CONVERT(INT, SUBSTRING(@julian,3,1)), 
 DATEADD(DAY, CONVERT(INT,SUBSTRING(@julian, 4, 3))-1, 
 0));

结果:

===================
2011-07-05 00:00:00

假设此数据不经常更改,将日期实际存储为计算列可能会更有效(这就是为什么我选择基日期0而不是某些字符串表示,这会导致确定性问题阻止列持久化并可能被索引)。

CREATE TABLE dbo.JDEDates
(
    JDEDate VARCHAR(6),

    GregorianDate AS CONVERT(SMALLDATETIME, 
      DATEADD(YEAR, 
        100*CONVERT(INT, LEFT(RIGHT('0'+JDEDate,6),1))
        +10*CONVERT(INT, SUBSTRING(RIGHT('0'+JDEDate,6), 2,1))
        +CONVERT(INT, SUBSTRING(RIGHT('0'+JDEDate,6),3,1)), 
      DATEADD(DAY, CONVERT(INT, RIGHT(JDEDate, 3))-1, 
      0))
    ) PERSISTED
);

INSERT dbo.JDEDates(JDEDate) SELECT '111186';

SELECT JDEDate, GregorianDate FROM dbo.JDEDates;

结果:

JDEDate GregorianDate
======= ===================
111186  2011-07-05 00:00:00

即使您没有为该列编制索引,它仍然会将丑陋的计算隐藏在您之外,被持久化您只需在写入时支付,因为它不会导致您在查询时执行昂贵的功能操作,只要该列被引用...

于 2012-03-12T17:29:26.707 回答
4

接受的答案不正确。它将无法给出 116060 的正确答案,它应该是 2016 年 2 月 29 日。相反,它会返回 2016 年 3 月 1 日。

JDE 似乎将日期存储为整数,因此我总是直接从整数转换,而不是从字符串转换:

DATEADD(DAY, @Julian % 1000, DATEADD(YEAR, @Julian / 1000, '31-dec-1899'))

从 varchar(6) 开始,我使用:

DATEADD(DAY, CAST(RIGHT(@Julian,3) AS int), DATEADD(YEAR, CAST(LEFT(@Julian,LEN(@Julian)-3) AS int), '31-dec-1899'))
于 2016-02-05T11:55:43.637 回答
1

DATE(CHAR(1900000 + GLDGJ)) 其中 GLDGJ 是儒略日期值

于 2015-12-15T15:11:16.077 回答
0
USE [master]
GO
/****** Object:  UserDefinedFunction [dbo].[ToGregorian]    Script Date: 08/18/2015 14:33:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[ToGregorian](@julian varchar(6),@time varchar(6))
RETURNS datetime 
AS 
BEGIN
    DECLARE @datetime datetime,@hour int, @minute int, @second int

    set @time = ltrim(rtrim(@time));
    set @julian = ltrim(rtrim(@julian));

    if(LEN(@julian) = 5)
        set @julian = '0' + @julian


    IF(LEN(@time) = 6)
        BEGIN
            SET @hour = Convert(int,LEFT(@time,2));
            SET @minute = CONVERT(int,Substring(@time,3,2));
            SET @second = CONVERT(int,Substring(@time,5,2));
        END
    else IF(LEN(@time) = 5)
        BEGIN
            SET @hour = Convert(int,LEFT(@time,1));
            SET @minute = CONVERT(int,Substring(@time,2,2));
            SET @second = CONVERT(int,Substring(@time,4,2));
        END
    else IF(LEN(@time) = 4)
        BEGIN
            SET @hour = 0;
            SET @minute = CONVERT(int,LEFT(@time,2));
            SET @second = CONVERT(int,Substring(@time,3,2));
        END
    else IF(LEN(@time) = 3)
        BEGIN
            SET @hour = 0;
            SET @minute = CONVERT(int,LEFT(@time,1));
            SET @second = CONVERT(int,Substring(@time,2,2));
        END
    else
        BEGIN
            SET @hour = 0;
            SET @minute = 0;
            SET @second = @time;
        END

    SET @datetime = DATEADD(YEAR,100*CONVERT(INT, LEFT(@julian,1))+10*CONVERT(INT, SUBSTRING(@julian, 2,1))+CONVERT(INT, SUBSTRING(@julian,3,1)),0);                     
    SET @datetime = DATEADD(DAY, CONVERT(INT,SUBSTRING(@julian, 4, 3))-1,@datetime);                   
    SET @datetime = DATEADD(hour,@hour,@datetime)
    SET @datetime = DATEADD(minute,@minute,@datetime);
    SET @datetime = DATEADD(second,@second,@datetime);

    RETURN @datetime
END
于 2015-08-18T18:45:08.223 回答
0

我认为没有人提到它,但是 JDE 有一个专门用于此的表。

这是F00365数据表。据我所知,这是一个专门针对这个问题的翻译表。

要获取公历日期,请使用 ONDTEJ 字段(即儒略日期)加入 F00365 表,然后返回 ONDATE 值,即公历日期。例如

SELECT 
    DateReq.ONDATE 
FROM F00101 NamesData 
INNER JOIN F00365 DateReq 
    ON DateReq.ONDTEJ = NamesData.ABUPMJ

不需要数学。闰年没有奇怪的问题。

于 2019-02-01T19:28:39.633 回答