【问题标题】:SQL - Julien Date (CYYDDD) to dateSQL - 朱利安日期 (CYYDDD) 至今
【发布时间】:2018-12-13 00:34:13
【问题描述】:

不幸的是,这是我第一次使用 SQL! 我正在使用以下代码在 oracle DB 和 Excel(Power Query)之间创建一个查询。

select "$Table"."Order" as "Order",
    "$Table"."NR" as "Nr",
    "$Table"."JDDATE" as "JDDATE"
from "POOLDB2"."3112" "$Table"
WHERE   "Key" >118001
    AND "CodeAA" = 1

此代码有效!

现在我想将儒略日期 (CYYDDD)(例如 01.01.2019 的 118001)格式化为正常的日期格式。 有谁知道,如何在上面的代码中实现这一点? 也许是这样的:

select "$Table"."Order" as "Order",
    "$Table"."NR" as "Nr",
    DATEADD(DAY, JDDATE % 1000 - 1, DATEADD(year, JDDATE/1000, 0))
    "$Table"."JDDATE" as "JDDATE"
from "POOLDB2"."3112" "$Table"
WHERE   "Key" >118001
    AND "CodeAA" = 1

最好的问候

【问题讨论】:

  • 这绝对是不是朱利安约会。儒略日期定义为自公元前 4713 年 1 月 1 日中午以来的天数。因此,两个相邻年份的同一天之间的 JD 差异为 365 或 366,而在 CYYDDD 格式中,则始终为 1000。您所拥有的是 序数日期 (en.wikipedia.org/wiki/Ordinal_date) .
  • 您确定 118001 应该是 2019-01-01 而不是 2018-01-01?
  • 是的,我的错。 118001是2018年1月1日,对不起

标签: sql oracle powerquery


【解决方案1】:

朱利安日期有许多不同的格式...在您的用例中,应该这样做:

with t as (select 118001 jd from dual)
select to_char( to_date(to_char(1901 + floor(jd / 1000)),'YYYY') + mod(jd,1000) - 1, 'dd.mm.yyyy' ) from t

产量:01.01.2019

【讨论】:

  • 这也适用于 oracle 吗?如何在上面的代码中实现这一点?
  • 我的答案确实是针对 Oracle 的,因为您在问题中提到了它(我也将您的问题标记为“oracle”)。它可能不适用于其他 RDBMS。
  • 谢谢!现在可以了。但为什么 118001 = 01.12.2019?应该是 01.01.2019,对吧?我怎样才能调整代码来得到这个? (DD.MM.YYYY)
  • @joshua1990 是的,我的错是错字,已修复。还调整了查询​​以匹配您预期的输出格式。
  • 对不起,我仍然得到 118019 的 19.12.2019 (dd.mm.yyyy)。但它应该是 19.01.2019。 (欧盟标准)。这是您的代码: to_char(to_date(to_char(1900 + floor("JDDATE" / 1000)), 'YYYY') + mod("JDDATE", 1000) -1, 'dd.mm.yyyy') as "Date ",
【解决方案2】:

对于甲骨文,

select to_char(sysdate,'J') from dual; --To Julian Date
select to_date(2456143,'J') from dual; --To Normal Date

必须工作。

编辑:抱歉,我没有看到 oracle 标记。

编辑:对于 OP 要求的行为

select to_date(to_char(1901 + floor(118001 / 1000)),'YYYY') from dual;

【讨论】:

  • Joshua 在他的问题中说他使用的是 Oracle,而不是 SQL Server
  • 不幸的是,这不起作用。我认为“@”不适合 oracle。对不起
  • 请再次检查我的答案
  • 给定 118001,这将返回 26/01/1990 - 不是 OP 要求的
【解决方案3】:

您可以使用您拥有的 118001 值,将其拆分为单独的年份和日期部分,方法是添加名义开始日期 1900-01-01(根据您的评论,118001 实际上是 2018-01-01,而不是 2019- 01-01):

select date '1900-01-01'
  + floor(118001 / 1000) * interval '1' year
  + (mod(118001, 1000) - 1) * interval '1' day
from dual;

DATE'1900-
----------
2018-01-01

或者通过提前一天开始固定日期,您可以删除显式 -1:

select date '1899-12-31'
  + floor(118019 / 1000) * interval '1' year
  + mod(118019, 1000) * interval '1' day
from dual;

DATE'1899-
----------
2018-01-19

这避免了必须构建更长的字符串来转换为日期,尽管您可以这样做(修改@GMB 的方法):

select to_date(to_char(1900 + floor(118001 / 1000)) || '-01-01', 'YYYY-MM-DD')
  + (mod(118001, 1000) - 1)
from dual;

您至少需要在to_date() 调用中指定月份,因为如果未提供,Oracle 默认为当前月份。这种行为是tucked away in the documentation

如果您指定的日期值没有时间分量,则默认时间为午夜。如果您指定的日期值不带日期,则默认日期为当月的第一天。

其中的第一部分是众所周知的并且是有道理的;第二部分不太明显,并没有明确说明它也适用于部分日期 - 所以如果您不提供年份,则使用当前年份;如果您不提供月份,则使用当前月份;但如果您不提供一天,则使用第一天。

您可以看到它对一些测试转换的作用:

select to_date('2018-12-25', 'YYYY-MM-DD') as demo_a,
  to_date('12:34:56', 'HH24:MI:SS') as demo_b,
  to_date('2019', 'YYYY') as demo_c,
  to_date('07-04', 'MM-DD') as demo_d,
  to_date('2019-01', 'YYYY-MM') as demo_e
from dual;

DEMO_A              DEMO_B              DEMO_C              DEMO_D              DEMO_E             
------------------- ------------------- ------------------- ------------------- -------------------
2018-12-25 00:00:00 2018-12-01 12:34:56 2019-12-01 00:00:00 2018-07-04 00:00:00 2019-01-01 00:00:00

【讨论】:

  • 是的,第一种方法很完美!非常感谢!我怎样才能得到一个没有时间的日期格式?
  • 你得到一个日期对象,它总是有一个时间分量,即使是午夜。但是,它没有任何内在的人类可读格式。如何显示它取决于您的客户端/应用程序。在我的演示中,我依赖于NLS_DATE_FORMAT,但如果您不希望客户端/应用程序处理它,您可以使用to_char() 将日期转换为特定格式的字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-17
  • 2020-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多