将JDE Julian日期转换为Gregorian

时间:2012-03-12 16:58:44

标签: sql sql-server-2005 tsql date julian

我正在尝试转换JDE dates,并积累了大量信息,并认为我会尝试执行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. 结果ex:111186 => 2011-07-05 00:00:00.000
  6. 在我看来,这有点笨拙和矫枉过正,我希望有更好的方法来做到这一点。也许我做了太多的转换,或者我应该一共使用不同的方法?

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

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

    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)
    

5 个答案:

答案 0 :(得分: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

即使你没有为列编制索引,它仍然会将丑陋的计算隐藏起来,因为它只是在写入时支付,因为它不会导致你在查询时执行昂贵的函数操作列被引用...

答案 1 :(得分:3)

接受的答案不正确。它将无法给出应该是2016年2月29日的116060的正确答案。相反它将于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'))

答案 2 :(得分:1)

DATE(CHAR(1900000 + GLDGJ))其中GLDGJ是朱利安日期值

答案 3 :(得分: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

答案 4 :(得分:0)

我认为没有人提到过它,但是JDE为此提供了一个表格。

这是F00365数据表。据我所知,这是一个转换表只是这个问题。

要获取公历日期,请使用ONDTEJ字段(这是儒略日期)联接F00365表,并返回ONDATE值,即公历日期。 例如

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

无需数学。 leap年没有奇怪的问题。