I am new in Lisp. I need to call datetime function. But I stuck at getting date time. Using UTC.
The code is
(defun C:test ()
(system-clock nil (get-universal-time))
)
The error:
Command: TEST
; error: no function definition: GET-UNIVERSAL-TIME
Anyone can help ? I'm using VisualLisp
There's a system variable called "CDATE", which has somehow more clear output than "DATE" system variable.
It gets the current date and time in your computer.
"CDATE"'s output format is "(4 digit year)(2 digit month)(2 digit day).(2 digit hours)(2 digit minutes)", and its in a decimal format like this 20170609.1410 for 2016/06/09 1:10 pm
So, to acquire current date in YYYY/MM/DD format your strategy will be like this:-
1- get the output and convert it to string
(setq cur_date (rtos (getvar "CDATE")))
2- extract year, month and day
(setq cur_year (substr cur_date 1 4))
(setq cur_month (substr cur_date 5 2))
(setq cur_day (substr cur_date 7 2))
3- construct your YYYY/MM/DD format
(setq cur_date (strcat cur_year "/" cur_month "/" cur_day))
Related
I am trying to convert April 2, 2012, 12:00 AM into a DATETIME/DATE/TIMESTAMP type I dont really mind just not a string.
The problem here however is that within the PARSE_DATETIME function the format string, specifically the %e element string which is for the single digit day is always preceded by a space and in my string I need a comma. The docs read The day of month as a decimal number (1-31); single digits are preceded by a space..
My parse function is as follows PARSE_DATETIME('%B %e, %Y, %I:%M %p','Timestamp) AS 'Date' but I get back the error No matching signature for function PARSE_DATETIME for argument types: STRING, DATETIME. Supported signature: PARSE_DATETIME(STRING, STRING) at [4:5]
Any help would be much appreciated.
You are likely seeing the error message because the timestamp field you are using is already a datetime. Your format string functions as expected with sample data:
with sample_data as (
select 'April 2, 2012, 12:00 AM' as input_string
)
select PARSE_DATETIME('%B %e, %Y, %I:%M %p', input_string) from sample_data
Which results in:
I would make sure your input data is as expected
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 write the code in Oracle SQL (like 'CCYYMMDD' into 102 )?
If someone will enter the date in the frontend, the value should return as 102 instead of date.
For that, how will write the function in Oracle PLSQL.
https://www.unece.org/trade/untdid/d00a/tred/tred2379.htm
These are the ANSI standard format.
You cannot write a function to determine which numeric date string corresponds to which format as the date string could be multiple formats:
For example, 010203 could be:
Format 2: DDMMYY 1st February 03
Format 3: MMDDYY 2nd January 03
Format 101: YYMMDD 3rd February 01
Format 306: DDHHMM 02:03 of Day 1
Format 402: HHMMSS 01:02:03
Format 405: MMMMSS 102 minutes 3 seconds
Format 610: CCYYMM March 0102
Format 616: CCYYWW Week 3 of 0102
Similarly 10080102 could be:
Format 4: DDMMCCYY 10th August 102
Format 102: CCYYMMDD 2nd January 1008
Format 305: MMDDHHMM 8th October 01:02
Format 501: HHMMHHMM Time span from 10:08 to 01:01
If anyone inserts the date in this format "CCYYMMDD" then the value should return only 102 as a default in the frontend. How to write the code in SQL?
You cannot, as I described above it is ambiguous what some values are and they could return multiple formats. Instead you should create another column and store the date format in that when the user inputs the date rather than trying to reconstruct the format code from an (ambiguous) number.
You can verify that a string fits a date format like this:
create or replace function is_CCYYMMDD
(p_str in varchar2)
return boolean
is
rv boolean;
dt date;
begin
begin
dt := to_date(p_str, 'YYYYMMDD');
dt := to_date('2000' || substr(p_str, 5), 'YYYYMMDD');
rv := true;
exception
when others then
rv := false;
end;
return rv;
end;
The first to_date() just checks that the whole string is a valid date. The second to_date() checks that the second half of the string is a valid month and day combo. This partly addresses #MTO observations about the problems of enforcing a strict format when some strings can fit more than one format.
Note that it is perfectly possible to have valid dates which pass this test despite being ambiguous e.g. is 20111012 in 'YYYYMMDD' or 'DDMMYYYY'? There is no way to be sure unless you enforce strict date formatting in the front-end input by using a date picker widget or separate input boxes for year, month and day.
why you pass '2000' in this query?
The second check verifies that the last four characters are valid as month and day. Whenever we do this sort of test we run into the problem of leap years. If we just apply to_date(str, 'MMDD') Oracle will default the year to the current year: the snag is 2018029 is not a valid date even though the original input of 20160229 is valid. My function avoids this by fixing the year element to 2000, which was a leap year.
Incidentally, if you want to use this function in SQL you'll need to change the return datatype to varchar2 (Y/N flag) or a number (1/0) because SQL doesn't support Booolean.
If you want to convert an Oracle date into a Julian date, then you can use the TO_CHAR function with 'j' as the format.
SELECT TO_CHAR(TO_DATE('BC47120412', 'BCYYYYMMDD'), 'J')
FROM DUAL;
Output: 0000102
If you want to convert julian date to oracle date then use query below,
SELECT TO_DATE(102, 'J')
FROM DUAL;
Output: 04/12/4712 12:00:00 AM BC
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 ********
tl;dr
Why am I not able to convert following string timestamp
select timestamp_format('2015-08-21 000000', 'YYYY-MM-DD HH24MISS') as timestamp
from sysibm.sysdummy1;
on an i7.1.0/OS machine?
Especially since I can convert
select timestamp_format('000000' , 'HH24MISS') as timestamp
from sysibm.sysdummy1;
to:
timestamp
-------------------------
2015-08-01 00:00:00.000000
Context
On an i7.1.0/OS machine, I have a table with timestamp data split up in several decimal columns, like
declare global temporary table tstamp
(
year dec(4,0),
month dec(2,0),
day dec(2,0),
time dec(6,0)
);
with data like
insert into session.tstamp
values (2015,8,21,92601),
(2015,8,21,132601);
on which I want to do some date filtering. Given the somewhat inflexible format, I figured that it is probably better if I convert this to a timestamp and use this to query the table. So i consulted the i/OS 7.1 Manual on timestamp_format
I started of with building the date part, ending up with
select
timestamp_format(YEAR || '-' || MONTH || '-' || DAY, 'YYYY-MM-DD') as timestamp
from session.tstamp;
which returns
TIMESTAMP
--------------------------
2015-08-21 00:00:00.000000
2015-08-21 00:00:00.000000
Perfect, let us add the time part and explicit lpad it to contain six characters:
select
timestamp_format(YEAR || '-' || MONTH || '-' || DAY || ' ' || lpad(TIME, 6, '0'), 'YYYY-MM-DD HH24MISS') as timestamp
from session.tstamp;
This results in the following error:
SQL State: 22007
Vendor Code: -20448
Message: [SQ20448] Expression not valid using format string specified for TIMESTAMP_FORMAT. Cause . . . . . : Argument 1 of the TIMESTAMP_FORMAT function can not be interpreted using the format string specified in argument 2 for one of the following reasons: -- The string expression is too short or too long. -- The string expression does not conform to the template specified in the format string. -- Too many digits were specified in the string expression for the corresponding format element in the format string. -- A value in the string expression is not valid for the corresponding format element in the format string. Recovery . . . : Specify a valid format string for the function. Try the request again.
According to the manual regarding the format-string, a separator between fields is optional:
[...]
Two format elements can optionally be separated by one or more of the following separator characters:
[...]
Question
So why are not my values accepted when using 'YYYY-MM-DD HH24MISS' as the format-string, given that I explicit has bound the time length to six characters?
Side note
It is possible to use HH24MISS on its own as format-string, so I'm not really able to wrap my head around this.
select timestamp_format(lpad(TIME, 6, '0'), 'HH24MISS') as timestamp from session.tstamp;
TIMESTAMP
--------------------------
2015-08-01 13:26:01.000000
2015-08-01 09:26:01.000000
The difficulties described, are due to defects with the TIMESTAMP_FORMAT [aka TO_DATE] scalar. The requests shown are tested to have functioned, as expected, with the DB2 for IBM i 7.3 [and as a comment to the OP suggests, also on v7r2]. I had asked a similar question, "Why the failures using my earlier examples?" in SQL convert text mm/dd/yy to date and timestamp, but I have not yet re-visited those examples on the newer release. And FWiW, there may be some updated code on IBM i 7.1 for that feature with the latest code; I do not have that level of maintenance, so I can not test if the [the last of the] enhancements that are coming for that release include the code fixes that apparently exist in newer releases.
Note that the TO_DATE feature is not a true built-in [instead, is a system-supplied User Defined Function (UDF)], so personally, I would recommend an alternative; namely, writing and using a scalar UDF specific to the task, and/or choose a more compatible and easy way to generate the TIMESTAMP from those columns as they are defined. Consider the following expression [that assumes all dates are beyond year 1000, else the expression must change to use DIGITS(YEAR) vs just YEAR]:
timestamp( YEAR concat digits( MONTH ) concat digits( DAY )
concat digits( TIME )
)
A variation of that, is to use arithmetic to achieve the same effect of a 14–character timestamp-string form 'yyyymmddhhmmss':
timestamp( concat( YEAR * 10000 + MONTH * 100 + DAY
, digits ( TIME ) ) )
The following scalar function could be created to avoid coding the expression in [VIEW] queries or other places. As coded, with nothing but an expression on a RETURN statement, should allow in-lining; I did not specify any other potentially performance-related clauses such as parallel or on-null-input:
create function y4m2d2t6TS
( year dec(4, 0)
, month dec(2, 0)
, day dec(2, 0)
, time dec(6, 0)
) returns timestamp
language sql deterministic
return
digits( YEAR ) concat digits( MONTH )
concat digits( DAY ) concat digits( TIME )
; -- this semicolon is a statement separator, not terminator of above CREATE
select
y4m2d2t6TS( year, month, day, time ) as timestamp
from session.tstamp
; -- likeness of report from above query:
TIMESTAMP
2015-08-21-09.26.01.000000
2015-08-21-13.26.01.000000
******** End of data ***
You can use this in DB2 :
values(VARCHAR_FORMAT(current_date,'YYYY-MM-DD HH24:MI:SS'))
Bye