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

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 ********

Related

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

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. :)

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)

SQL Server 2012 - Convert CYYMMDD date to YYYYMMDD

I have a table with just over 200,000 entries where the date is stored as CYYMMDD where C is the century (currently stored as integers). For example, December 5, 1992 would show up as 1921205 and April 25, 2016 would show up as 2160425. I need to display these results in a new table in a YYYMMDD format. So for the two examples earlier it would be 19921205 and 20160425. I have tried using
CONVERT(VARCHAR(8),[DATE], 112)
This doesn't give an error but it also doesn't do the conversion so all my dates still look the same. What am I doing wrong?
You'll need to split your numeric value as follows:
DATEFROMPARTS( 1800 + FLOOR([DATE]/10000) , FLOOR([DATE]/100)%100, [DATE]%100 )

Format date where the position of the parts is variable

We have a file that needs to be imported that has dates in it. The dates are in a format that I have not seen before and the day part can vary in length (but not the month or year seemingly) and position based on wether the number is double digit or not, i.e.
Dates:
13082014 is 13th February 2014
9092013 is 9th September 2013
The current script tries to substring the parts out, but fails on the second one as there is not enough data. I could write an if or case to check the length, but is there a SQL format that can be used to reliably import this data?
To clarify this is MSSQL and the date format is ddmmyyyy or dmmyyyy
One of the simple way is using STUFF.
example:
select STUFF(STUFF('13082014 ',3,0,'/'),6,0,'/');
//result: 13/08/2014
Good luck.
LPAD a zero when it is missing so to always get an eight character date string. Here is an example with Oracle, other DBMS may have other string and date functions to achieve the same.
select to_date(datestring, 'ddmmyyyy')
from
(
select lpad('13082014', 8, '0') as datestring from dual
union all
select lpad('9092013', 8, '0') as datestring from dual
);
Result:
13.08.2014
09.09.2013
you can convert the dates to a relevant date format then import data(based on the dateformat change the logic).
something like this :
select Convert(varchar(10),CONVERT(date,YourDateColumn,106),103)

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>