SQL - Julien Date (CYYDDD) to date

陌路散爱 提交于 2019-12-11 09:54:08

问题


Unfortunately, this is my first approach with SQL! I am creating with the following code a query between an oracle DB and 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

This code works!

Now I want to format the Julian Date (CYYDDD) - for example 118001 for the 01.01.2019 - to a normal date format. Does anyone know, how to implement this into the code above? Maybe something like :

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

Best regards


回答1:


There are many different formats for Julian Date... In your use case, this should do it :

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

Yields : 01.01.2019




回答2:


For Oracle,

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

must work.

Edit: Sorry I didn't see oracle tag.

Edit: For the requested behavior by OP

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



回答3:


You can use the 118001 value you have, split into separate year and day sections, by adding to the nominal starting date 1900-01-01 (based on your comment that 118001 is actually 2018-01-01, not 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

or by startng the fixed date a day earlier you can remove the explicit -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

This avoids having to build up a longer string to convert to a date, though you could do that (modifying @GMB's approach) as:

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

You need to specify the month, at least, in the to_date() call as Oracle defaults to the current month if that is not supplied. That behaviour is tucked away in the documentation:

If you specify a date value without a time component, then the default time is midnight. If you specify a date value without a date, then the default date is the first day of the current month.

The first part of that is fairly well known and makes sense ; the second part is a bit less obvious, and doesn't make it clear that it applies to partial dates too - so ifyou don't supply a year then the current year is used; if you don't supply a month then the current month is used; but if you don't supply a day then the 1st is used.

You can see what it's doing with some test conversions:

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


来源:https://stackoverflow.com/questions/53743601/sql-julien-date-cyyddd-to-date

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!