How to retrieve date from a Rundeck job - rundeck

I'm trying to achieve something like this in a rundeck 2.6 job:
touch /foo/bar/${DATE:MM/dd/yyyy}-baz
but it doesn't work properly and the date is not interpreted at all. Is there a proper way to do this?

You can use this bash script :
#!/bin/bash
touch /foo/bar/`date "+%m/%d/%Y"`-baz
The backquotes act as command substitution and replace the output of the date command in the touch command.
According to the date man page :
An operand with a leading plus (`+') sign signals a user-defined format string which
specifies the format in which to display the date and time. The format string may contain any of the conversion specifications described in the strftime(3) manual page, as
well as any arbitrary text.
The date format string use the following conversion specifier character :
%m The month as a decimal number (range 01 to 12). (Calculated
from tm_mon.)
%d The day of the month as a decimal number (range 01 to 31).
(Calculated from tm_mday.)
%Y The year as a decimal number including the century.
(Calculated from tm_year)

You can also define an option that uses that date format specifier.
Set the default value of the option to use the specifier. Eg:
<option name="date" value="${DATE:MM/dd/yyyy}-baz" />
Inside your step reference the ${option.date}.

Related

Unix string to date conversion, what is wrong

I know the topic has already emerged and some of the posts give a good summary like the one here: Convert string to date in bash . Nevertheless, I encounter a problem presented below with an example I should solve:
date +'%d.%m.%y' works as desired and returns 05.12.20 but the inverse operation I should use to convert strings to date fails:
date -d "05.12.20" +'%d.%m.%y'
date: invalid date ‘05.12.20’
and this is exactly what I need. The Unix date formatting I have also checked on https://www.cyberciti.biz/faq/linux-unix-formatting-dates-for-display/ but it seems to be in line with that. What is the problem? I also tried to supply time zone indicators like CEST but they did not solve the problem.
Try
date -d "05-12-20" +'%d.%m.%y'
UNIX date expects either - or / as a date separator.
However, if your input really must be in the format "05.12.20" (i.e. using .), then you can convert it to the format expected by UNIX date:
date -d `echo "05.12.20" | sed 's/\./-/g'` +'%d.%m.%y'

How to format the time as following "2018-03-15T23:47:15+01:00"

With java.time , I'm trying to format the time as the following "2018-03-15T23:47:15+01:00" .
With this formatter I'm close to the result in Scala.
val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssZ")
ZonedDateTime.now() // 2018-03-14T19:25:23.397+01:00
ZonedDateTime.now().format(formatter) // => 2018-03-14 19:25:23+0100
But I cannot insert the extra character "T" between the day and hour.
What does this "T" mean BTW ?
How to format as "2018-03-15T23:47:15+01:00" ?
Notes:
In case you wonder why LocalDateTime cannot be formatted
Format LocalDateTime with Timezone in Java8
Try this
val ZONED_DATE_TIME_ISO8601_FORMATTER3 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx")
ZonedDateTime.now().format(ZONED_DATE_TIME_ISO8601_FORMATTER3)
// 2018-03-14T19:35:54.321+01:00
See here
Offset X and x: This formats the offset based on the number of pattern letters. One letter outputs just the hour, such as '+01', unless the minute is non-zero in which case the minute is also output, such as '+0130'. Two letters outputs the hour and minute, without a colon, such as '+0130'. Three letters outputs the hour and minute, with a colon, such as '+01:30'. Four letters outputs the hour and minute and optional second, without a colon, such as '+013015'. Five letters outputs the hour and minute and optional second, with a colon, such as '+01:30:15'. Six or more letters throws IllegalArgumentException. Pattern letter 'X' (upper case) will output 'Z' when the offset to be output would be zero, whereas pattern letter 'x' (lower case) will output '+00', '+0000', or '+00:00'.
Converting the ZonedDateTime to OffsetDateTime - as suggested in the other answers - works, but if you want to use a DateTimeFormatter, there's a built-in constant that does the job:
ZonedDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
But it's important to note some differences between all the approaches. Suppose that the ZonedDateTime contains a date/time equivalent to 2018-03-15T23:47+01:00 (the seconds and milliseconds are zero).
All the approaches covered in the answers will give you different results.
toString() omits seconds and milliseconds when they are zero. So this code:
ZonedDateTime zdt = // 2018-03-15T23:47+01:00
zdt.toOffsetDateTime().toString()
prints:
2018-03-15T23:47+01:00
only hour and minute, because seconds and milliseconds are zero
The built-in formatter will omit only the milliseconds if it's zero, but it'll print the seconds, regardless of the value. So this:
zdt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
prints:
2018-03-15T23:47:00+01:00
seconds printed, even if it's zero; milliseconds ommited
And the formatter that uses an explicit pattern will always print all the fields specified, regardless of their values. So this:
zdt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx"))
prints:
2018-03-15T23:47:00.000+01:00
seconds and milliseconds are printed, regardless of their values
You'll also find a difference in values such as 2018-03-15T23:47:10.120+01:00 (note the 120 milliseconds). toString() and ofPattern will give you:
2018-03-15T23:47:10.120+01:00
While the built-in DateTimeFormatter.ISO_OFFSET_DATE_TIME will print only the first 2 digits:
2018-03-15T23:47:10.12+01:00
Just be aware of these details when choosing which approach to use.
As your question already shows, you may just rely on ZonedDateTime.toString() for getting a string like 2018-03-14T19:25:23.397+01:00. BTW, that string is in ISO 8601 format, the international standard. Only two minor modifications may be needed:
If you don’t want the fraction of second — well, I don’t see what harm it does, it agrees with ISO 8601, so whoever receives your ISO 8601 string should be happy to have it. But if you don’t want it, you may apply myZonedDateTime.truncatedTo(ChronoUnit.SECONDS) to get rid of it.
ZonedDateTime.toString() often appends a zone name, for example 2018-03-14T19:25:23+01:00[Europe/Paris], which is not part of the ISO 8601 standard. To avoid that, convert to OffsetDateTime before using its toString method: myZonedDateTime.toOffsetDateTime().toString() (or myZonedDateTime.truncatedTo(ChronoUnit.SECONDS).toOffsetDateTime().toString()).
Building your own formatter through a format pattern string is very flexible when this is what you need. However, very often we can get through with less (and then should do for the easier maintainability of our code): toString methods or built-in formatters including both the ISO ones and the localized ones that we can get from DateTimeFormatter.ofLocalizedPattern().
What does this "T" mean BTW ?
The T is part of the ISO 8601 format. It separates the date part from the time-of-day part. You may think of it as T for time since it denotes the start of the time part. If there is only a date (2018-04-25) or only a time-of-day (21:45:00), the T is not used, but when we have both, the T is required. You may think that the format might have been specified without the T, and you are probably right. When it comes to the format for periods/durations it is indispensable, however, and also needed when there are no days: P3M means a period of 3 months, while PT3M means 3 minutes.
Link: Read more in the Wikipedia article on ISO 8601.

Why does strptime from Time::Piece not parse my format?

My collegue (who has left the company) has written a bunch of scripts, including batch and Perl scripts, and I'm getting rid of the regional settings dependencies.
In the last Perl script, he's written the following piece of code:
my $format = "%d.%m.%Y %H:%M";
my $today_converted = Time::Piece->strptime($today, $format) - ONE_HOUR - ONE_HOUR - ONE_HOUR - ONE_HOUR - ONE_HOUR;
(the idea is to get five hours before midnight of that particular date)
The value of $today seems to be "03/04/2017" (which stands for the third of April (European dateformat)), which seems not to be understood by Time::Piece implementation:
Error parsing time at C:/Perl64/lib/Time/Piece.pm line 481.
Which format can I use which is understood by Time::Piece Perl implementation?
In the format you have dots . as the date delimiter, but in the data you have slashes /. That's why it doesn't parse. It needs an exact match.
I think it's worth clarifying that strptime() will parse most date and time formats - that's the point of the method. But you need to define the format of the date string that you are parsing. That's what the second parameter to strptime() (in this case, your $format variable) is for.
The letters used in the format are taken from a standard list of definitions which used by every implementation of strptime() (and its inverse, strftime()). See man strptime on your system for a complete list of the available options.
In your case, the format is %d.%m.%Y %H:%M - which means that it will parse timestamps which have the day, month and year separated by dots, followed by a space and the hours and minutes separated by a colon. If you want to parse timestamps in a different format, then you will need to change the definition of $format.

Using nzload to upload a file with two differing date formats

I am trying to load onto Netezza a file from a table in an Oracle database, the file contains two separate date formats - one field has the format
DD-MON-YY and the second field has the format DD-MON-YYYY hh24:MI:SS, is there any with in NZLOAD to cater for two different date formats within a file
Thanks
rob..
If your file is fixed-length, you can use zones
However, if its field delimited, you can use some of the preprocessing tools like sed to convert all the date / timestamp to one standard format, before piping the output to nzload.
for ex.,
1. 01-JAN-17
2. 01-JAN-2017 11:20:32
Lets convert the date field to same format
cat output.dat |\
sed -E 's/([0-9]{2})-([A-Z]{3})-([0-9]{2})/\1-\2-20\3/g' |\
nzload -dateStyle DMONY -dateDelim '-'
sed expression is pretty simple here, let's break it down
# looking for 2 digits followed by
# 3 characters and followed by
# 2 digits all separated by '-'
# elements are grouped with '()' so they can be referred by number
's/([0-9]{2})-([A-Z]{3})-([0-9]{2})
# reconstruct the date using group number and separator, prefix 20 to YY
/\1-\2-20\3
# apply globally
/g'
also in nzload we have specified the format of date and its delimiter.
Now we'll have to modify the regular expression depending upon different date formats and what they are getting converted to, this may not be an universal solution.

How do I parse "YYYY-MM-DD" with joda time

I'm trying to use joda-time to parse a date string of the form YYYY-MM-DD. I have test code like this:
DateTimeFormatter dateDecoder = DateTimeFormat.forPattern("YYYY-MM-DD");
DateTime dateTime = dateDecoder.parseDateTime("2005-07-30");
System.out.println(dateTime);
Which outputs:
2005-01-30T00:00:00.000Z
As you can see, the DateTime object produced is 30 Jan 2005, instead of 30 July 2005.
Appreciate any help. I just assumed this would work because it's one of the date formats listed here.
The confusion is with what the ISO format actually is. YYYY-MM-DD is not the ISO format, the actual resulting date is.
So 2005-07-30 is in ISO-8601 format, and the spec uses YYYY-MM-DD to describe the format. There is no connection between the use of YYYY-MM-DD as a pattern in the spec and any piece of code. The only constraint the spec places is that the result consists of a 4 digit year folowed by a dash followed by a 2 digit month followed by a dash followed by a two digit day-of-month.
As such, the spec could have used $year4-$month2-$day2, which would equally well define the output format.
You will need to search and replace any input pattern to convert "Y" to "y" and "D" to "d".
I've also added some enhanced documentation of formatting.
You're answer is in the docs: http://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html
The string format should be something like: "yyyy-MM-dd".
The date format described in the w3 document and JodaTime's DateTimeFormat are different.
More specifically, in DateTimeFormat, the pattern DD is for Day in year, so the value for DD of 30 is the 30th day in the year, ie. January 30th. As the formatter is reading your date String, it sets the month to 07. When it reads the day of year, it will overwrite that with 01 for January.
You need to use the pattern strings expected by DateTimeFormat, not the ones expected by the w3 dat and time formats. In this case, that would be
DateTimeFormatter dateDecoder = DateTimeFormat.forPattern("yyyy-MM-dd");