How to convert four-digit Julian (yddd) to Gregorian (mm/dd/yy, etc.) in script loader? - sql

The Goal
To have the data script handle the logic and conversion to a date format that is parsable/readable by a QlikSense/QlikView line graph. AKA it needs to be a normal format. (YYYYMMDD, MM/DD/YY, etc.)
Context
All relevant tables to the date is in one table.
The field the date data is in is called "date", and is successfully referenced in Qliksheets by using [Date]
ddd is the Day of the Year. y is the last digit of the year. The decade is assumed to be 2010s, therefore we can safely add "201" before the digit, giving you the year.
Examples of four-digit Julian: 9001 is January 1st, 2019. 9283 is October 10th, 2019
What I've Tried
I've been going along the route of simply adding "201" before the first digit of the provided four-digit number, and then calculating the last/next three digits of the four-digit number.
Currently, I haven't even gotten to the calculation part, as I can't even get the string concatenation to work. All my attempts have circulated around the following:
[AwesomeSheet]:
LOAD
Right([Date], 3) as JulianDay, // Get day
Left([Date], 1) as JulianYearSingleDigit, // Get year
201 & JulianYearSingleDigit & JulianDay as TempField // Attempt to concatenate the numbers
// Here be the JulianDay calculation
Date#([TempField], 'YYYYMMDD') as FormattedDate // Format into readable format for line graph
FROM [my-awesome-file.csv];

Possible solution is to get the year start date, add the number of days to it and convert to date:
date(
date#( '201' & left([Date], 1) & '0101', 'YYYYMMDD')
-1
+ num( mid([Date], 2,4) )
)
What the calculation is doing:
getting the first character from the date left([Date], 1)
adds 201 to format it as year number '201' & left([Date], 1)
adds 0101 to it '201' & left([Date], 1) & '0101'
(at this point this part will be equal to 20190101 (as string))
date#( '201' & left([Date], 1) & '0101', 'YYYYMMDD') - this will "tell" Qlik that the string inside is a date in format YYYYMMDD
to the year start we'll add the days (last 3 symbols from the original string) num( mid([Date], 2,4) )
cast all to date
As a result 9283 = 10/10/2019
So your script will look like:
[AwesomeSheet]:
LOAD
date(
date#('201' & left([Date], 1) & '0101', 'YYYYMMDD')
-1
+ num( mid([Date], 2,4) )
) as FormattedDate
FROM [my-awesome-file.csv];
Thats one possible way. There might be shorter/easier way but this is on top of my head

It sounds like what you want is a dayOfYearToYmd converter - this might help "Convert day of year to datetime in SQL Server"
Also, these might help regarding the concept of Julian dates:
https://en.wikipedia.org/wiki/Julian_day
http://www.fourmilab.ch/documents/calendar/
Julian days simply enumerate the days and fraction which have elapsed since the start of the Julian era, which is defined as beginning at noon on Monday, 1st January of year 4713 B.C.E. in the Julian calendar.
, ie any date before the reference date has a negative value, anything after is positive, which doesn't fit with your post.
Given the above, you could declare the start of each calendar year as a reference date. :)

Related

Selecting week / ISO week number from a date/time field

Sorry - this may be a basic question, but I have been banging my head against this for a week.
I have a database field with the format "dd/mm/yyyy hh:mm:ss" called UpdateTime and referencing max(AuditHistory.ActionedDateTime) in the database.
I am trying to identify the Week / ISO Week from the date part of this field only using the dataset in ReportBuilder3.
I am trying to achieve an integer entry in a column called "WeekNo" giving me the week of the year that a transaction was made so I can use this for grouping results by year | by week number on a report for senior management.
I have tried many combinations of:
,DATEPART(WEEK,DAY(max(AuditHistory.ActionedDateTime)) AS WeekNo and
,DATEPART(WEEK,MONTH(max(AuditHistory.ActionedDateTime)) AS WeekNo.
If I use a static date, e.g. , DATEPART(WEEK,DAY('1900-01-20')) AS WeekNo, it returns perfectly as "4" but I cannot for the life of me get the datepart format correct to identify the week from the format of the field.
I believe my issue is getting SQL to accept that the field is "dd/mm/yyyy hh:mm:ss" and work out the week from the date element.
Before I go mad - I thought I'd ask if there is a quick way to achieve this.
The DATEPART function expects a date / datetime / datetime2 value. You are passing in an integer representing the day or month number.
Assuming you're storing your dates correctly, you just need to pass in the date value directly:
DATEPART(WEEK, Max(AuditHistory.ActionedDateTime)) As WeekNo

How To change long date to date

How To change Long Date To short Date
E.g (Sunday, January 10, 2018)--Long Date
E.g (2018-01-10)
You can convert the string to a date, once you get rid of the day-of-week:
select convert(date, stuff(longdate, 1, charindex(' ', longdate), ''))
select convert(DATE, 'May 23 2019',101)
or
select convert(DATE, 'January 10 2018',101)
January 10th 2018 was a Wednesday
I think you might be confused; properly stored a date is just a date - a number, if you like, or the count of days (and fractions of days) since some point in time. It doesn't have any text in its internal representation and cannot be shortened.
When you select it in a query the query tool has to represent it somehow and for that it will format it into a string that you'll interpret as an entry on your wall calendar. For the most part we should avoid getting the db to format anything, because fornatting is the job of the presentation layer; the website that pulled your date out of the db and now has to make it look like the German way of writing a date because Hans Schmidt is logged in, but later format it as American when John Doe is browsing
If you're desperate to format it in the db use
FORMAT(thedate, 'yyyy-MM-dd')
Or maybe
LEFT(CONVERT(thedate, varchar, 120), 10)

How to compare 2 converted dates in sql

I'm trying to exclude results in my query that start in the same month between two columns. For example, I need to exclude benefits1 that start in the same month as benefits2. Format for benefit1_start_date and benefit2_start_date is: YYYYMMDD.
This is what I have so far:
where (benefit1_start_date = (to_char(sysdate, 'YYYYMM') || '0122')) <>
(benefit2_start_date = (to_char(sysdate, 'YYYYMM') || '0122'));
If anyone could put me in the right direction, I'd greatly appreciate it!
Convert your numeric dates to text, and then compare the year and month substrings:
WHERE
SUBSTR(TO_CHAR(benefits1_start_date), 1, 6) <> SUBSTR(TO_CHAR(benefits2_start_date), 1, 6)
Note that storing your dates as numbers like this is atypical, and you might want to consider storing them as dates. If you don't have a day component, you could just use the first as a placeholder.
As I understand it, you want to eliminate records where your 2 columns benefits1_start_date and benefits2_start_date are in the same month, and both have a format of YYYYMMDD.
Are they stored as strings? If so, all you need to do is compare the first 6 characters (if you need to consider yr + month), or just the 5+6th characters if you want to check just the month without the year.
Year + Month:
SUBSTR(benefits1_start_date,1,6) <> SUBSTR(benefits2_start_date,1,6)
Just month:
SUBSTR(benefits1_start_date,5,2) <> SUBSTR(benefits2_start_date,5,2)
If they're not stored as strings but as dates, then you can TRUNC the date to month and compare (for yr + month), or convert the date to MM string via to_char and compare if you just want to check the month.
Hope this helps.
I suggest you to use BETWEEN clause. Converting LEFT side operand to string by function and then making comparison can have severe performance impacts.
if you convert indexed table.dateColumn to string by to_char(table.dateColumn), oracle cannot use defined index on column anymore.
Your desired query:
where to_char(benefit1_start_date, 'YYYYMM') != to_char(benefit2_start_date, 'YYYYMM')
but
select * from table1
where months_between(benefit1_start_date, benefit2_start_date) not between -1 and 1
would be what you are looking for. (no performance impact)

AS400 Emulator cant process dates less than 1940 or greater than 2039

I have this simple SQL script:
SELECT DATE(SUBSTR( '19310205' , 1 , 4)
|| '-' || SUBSTR ('19310205' , 5 , 2)
|| '-' || SUBSTR('19310205', 7 , 2))
FROM MY_TABLE;
Whenever I run the script on the iSeries navigator, I get the expected output which is
1931-02-05
However, when I run it on the AS400 Emulator using the strsql command, I get the following output:
++++++++
I have no idea why this happens; all I know is that only the dates between 1940-2039 are working well. Can anyone explain why?
Also, is there a way for the other dates be processed successfully as well?
In your AS/400 emulator session, press "F13=Services".
Select "1. Change Session Attributes"
Change the "Date Format" to "*ISO" or desired format supporting a full date range.
From the IBM Knowledge Center, "Rational Developer for i7.1.0":
A date is a three-part value (year, month, and day) designating a point in time >under the Gregorian calendar20, which is assumed to have been in effect from >the year 1 A.D. The range of the year part is 0001 to 9999. The date formats >*JUL, *MDY, *DMY, and *YMD can only represent dates in the range 1940 through >2039. The range of the month part is 1 to 12. The range of the day part is 1 to >x, where x is 28, 29, 30, or 31, depending on the month and year.
I just want to build on Richard Evans answer, but since there is too much to put into a comment, I will make it a new answer.
IBM i has a native date type that can store dates from January 1, 0001 to December 31, 9999. The date type has a format which specifies, among other things, the number of digits in the year portion of the date. There are two main groupings that affect the range of dates that can be accepted. Two digit year formats which can accept dates from January 1, 1940 - December 31, 2039. These are: *MDY, *DMY, *YMD, and *JUL. Four digit year formats can handle the full range of dates that the date type supports. These are *ISO, *USA, *EUR, *JIS.
In addition to the main formats which are supported everywhere date formats are supported, RPG supports a few other date formats: *JOBRUN, three digit year formats, and *LONGJUL. *JOBRUN is a two digit year format, and can only be specified for numeric and character date fields with 2 digit years. This uses the job date format and seperator values. Three digit year formats can handle dates from January 1, 1900 - December 31, 2899. These are *CMDY, *CDMY, and *CYMD. The C in the three digit year formats represents the two most significant digits of the year portion of the date where:
0 => 1900 - 1999
1 => 2000 - 2099
2 => 2100 - 2199
...
9 => 2800 - 2899
Finally *LONGJUL is a four digit year Julian format.
Internally dates are stored in an *ISO format. The other formats are external formats. In fact when defining tables with SQL you don't even get to specify the date format, it just defaults to *ISO. In places that you can specify the format, it is just an external format that you are specifying. It is best to use *ISO for all working fields and database files, even when using DDS. Then reserve other external formats like *MDY or *DMY for user facing fields to convert the *ISO format into a more localized format. This way you can store the full range of dates that users can input or view.
Return a character representation of a date in any format using the varchar_format() function. Regardless of session defaults or where its run from.
SELECT
cast(
varchar_format(
cast(
DATE(SUBSTR( '19310205' , 1 , 4)
|| '-' || SUBSTR ('19310205', 5 , 2)
|| '-' || SUBSTR('19310205', 7 ,2))
as timestamp )
, 'YYYY-MM-DD')
as char(10)) as mydate
FROM sysibm/sysdummy1
MYDATE
1931-02-05
******** End of data ********

Julian Date Conversion SQL

How to convert the Julian date to Gregorian Calendar date in SQL Server? Below are the cases:
6 digit number - I have done the conversion and it is working fine
5 digit number - I don't have any idea about how to convert this Julian date to normal date. I did search in Google websites, but each websites have different answers, so I am confused. Example data (47315, 45009, 69064, 99281, 98222, 98329)
If I have the value "0" in the Julian date column, then how to convert this value to Gregorian date?
That second scenario looks like YYJJJ format.
Converting it would look something like
SELECT DATEADD(dd, CAST(RIGHT(yourdate, 3) AS integer) - 1, CONVERT(smalldatetime,'01/01/' + LEFT(yourdate, 2), 3)) AS converteddate
FROM <yourtable>