Why Golang time format (RFC-822 in this case) is different from the one described in the RFC?
In time package RFC822 const value is defined as:
RFC822 = "02 Jan 06 15:04 MST"
11 Nov 09 00:00 CET
But regarding to RFC-822 or w3.org Validator date format should be rather as RFC1123:
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
Wed, 11 Nov 2009 00:00:00 CET
or even better:
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700"
Wed, 11 Nov 2009 00:00:00 +0100
Because the Central European Time Zone (CET) is not correct in this RFC.
Why such a difference?
I'm writing an RSS server and it took me a while to figure out why I'm getting badly formatted results.
Related
I wanted to construct a spring cron expression that executes At 23:00:00pm, on first Sunday, every 2 months starting in January, so far I have this
0 0 23 ? 1/2 SUN but this one executes At 23:00:00pm, every Sunday, every 2 months starting in January. how can I make it execute only the first Sunday every two months?
0 0 23 ? 1/2 SUN next excution dates are as follows
Sun Mar 07 23:00:00 UTC 2021
Sun Mar 14 23:00:00 UTC 2021
Sun Mar 21 23:00:00 UTC 2021
Sun Mar 28 23:00:00 UTC 2021
Sun May 02 23:00:00 UTC 2021
Sun May 09 23:00:00 UTC 2021
Sun May 16 23:00:00 UTC 2021
Sun May 23 23:00:00 UTC 2021
Sun May 30 23:00:00 UTC 2021
Sun Jul 04 23:00:00 UTC 2021
but what I wanted was
Sun Mar 07 23:00:00 UTC 2021
Sun May 02 23:00:00 UTC 2021
Sun Jul 04 23:00:00 UTC 2021
how can I improve my expression to get the above result?
0 0 23 1-7 1/2 SUN
The only part you are missing, is day number in the range 1-7.
Code to verify the schedule:
var sundays = CronExpression.parse("0 0 23 1-7 1/2 SUN");
var nextDate = LocalDateTime.now();
var dateFormatter = DateTimeFormatter.ofPattern("EEE, MMM d, yyyy 'at' hh:mm:ss a");
for (var i = 0; i < 10; i++) {
nextDate = sundays.next(nextDate);
System.out.println(nextDate.format(dateFormatter));
}
Will run at:
Sun, Mar 7, 2021 at 11:00:00 pm
Sun, May 2, 2021 at 11:00:00 pm
Sun, Jul 4, 2021 at 11:00:00 pm
Sun, Sep 5, 2021 at 11:00:00 pm
Sun, Nov 7, 2021 at 11:00:00 pm
...
I want to automate a task quarterly in a year.
Task should execute
Jan 1st
April 1st
July 1st
October 1st
etc
As I tried #Scheduled(cron = "0 0 6 1 1/3 ?") in Spring Boot application but its not working currently and mail didn't trigger quarterly.
Try this
#scheduled(cron = "0 0 6 1 */3 *")
So read the first day of each 3 month at 6:00
Try this one -
#scheduled(cron ="0 0 0 1 JAN,APR,JUL,OCT ? *")
Next execution:
Wed Jul 01 00:00:00 UTC 2020
Thu Oct 01 00:00:00 UTC 2020
Fri Jan 01 00:00:00 UTC 2021
Thu Apr 01 00:00:00 UTC 2021
Thu Jul 01 00:00:00 UTC 2021
Fri Oct 01 00:00:00 UTC 2021
Sat Jan 01 00:00:00 UTC 2022
Fri Apr 01 00:00:00 UTC 2022
Fri Jul 01 00:00:00 UTC 2022
Sat Oct 01 00:00:00 UTC 2022
I have a list of files with the substring YYYYMMDDHH in them (example: 2016112200 means 2016 November 22th at 00 hours). These files are: temp_2016102200.data, temp_2016102212.data, temp_2016102300.data, temp_2016102312.data, ..., temp_20170301.data. And I also have other family of files substituting temp by wind.
For each string YYYYMMDDHH I want to create a tar with the temp and its correspondent wind file. I don't want this process to stop if one or both files are missing.
My idea was to loop from 12 hours to 12 hours, but I am having some problems because to specify the date I did: b=$(date -d '2016111400' +'%Y%m%d%H') but bash informs me that that is not a valid date...
Thanks.
It's not bash telling you the date format is wrong: date is telling you. Not everything you type is a bash command.
As Kamil comments, you have to split it up so that date can parse it. The YYYY-mm-dd HH:MM:SS format is parsable. Using bash parameter expansion to extract the relevant substrings:
$ d=2016111400
$ date -d "${d:0:4}-${d:4:2}-${d:6:2} ${d:8:2}:00:00"
Mon Nov 14 00:00:00 EST 2016
Now, when you want to add 12 hours, you have to be careful to do it in the right place in the datetime string: if you add a + character after the time, it will be parsed as a timezone offset, so put the relative part either first or between the date and the time.
$ date -d "+12 hours ${d:0:4}-${d:4:2}-${d:6:2} ${d:8:2}:00:00"
Mon Nov 14 12:00:00 EST 2016
As a loop, you could do:
d=2016111400
for ((i=1; i<=10; i++)); do
# print this datetime
date -d "${d:0:4}-${d:4:2}-${d:6:2} ${d:8:2}:00:00"
# add 12 hours
d=$( date -d "+12 hours ${d:0:4}-${d:4:2}-${d:6:2} ${d:8:2}:00:00" "+%Y%m%d%H" )
done
outputs:
Mon Nov 14 00:00:00 EST 2016
Mon Nov 14 12:00:00 EST 2016
Tue Nov 15 00:00:00 EST 2016
Tue Nov 15 12:00:00 EST 2016
Wed Nov 16 00:00:00 EST 2016
Wed Nov 16 12:00:00 EST 2016
Thu Nov 17 00:00:00 EST 2016
Thu Nov 17 12:00:00 EST 2016
Fri Nov 18 00:00:00 EST 2016
Fri Nov 18 12:00:00 EST 2016
OK, a "nicer" way to loop
start=2019043000
end=2019050300
plus12hours() {
local d=$1
date -d "+12 hours ${d:0:4}-${d:4:2}-${d:6:2} ${d:8:2}:00:00" "+%Y%m%d%H"
}
for (( d = start; d <= end; d = $(plus12hours "$d") )); do
printf "%d\t%s\n" "$d" "$(date -d "${d:0:4}-${d:4:2}-${d:6:2} ${d:8:2}:00:00")"
done
2019043000 Tue Apr 30 00:00:00 EDT 2019
2019043012 Tue Apr 30 12:00:00 EDT 2019
2019050100 Wed May 1 00:00:00 EDT 2019
2019050112 Wed May 1 12:00:00 EDT 2019
2019050200 Thu May 2 00:00:00 EDT 2019
2019050212 Thu May 2 12:00:00 EDT 2019
2019050300 Fri May 3 00:00:00 EDT 2019
DateTime#parse on 'Mon, 30 Dec 2013 00:00:00 UTC +00:00' is wrong for the week. I chose ISO 8601 week-based year and week number %V (week number 01..53 of the week-based year).
With format "%V-%y":
DateTime.parse('Mon, 30 Dec 2013 00:00:00 UTC +00:00').strftime "%V-%y"
#⇒ "01-13"
DateTime.parse('Mon, 30 Dec 2013 00:00:00 UTC +00:00').strftime "%W-%y"
#⇒ "52-13"
Date.strptime('01-13', '%V-%y')
#⇒ Tue, 01 Jan 2013
Date.strptime('52-13', '%V-%y')
#⇒ Tue, 01 Jan 2013
Mon, 30 Dec 2013 00:00:00 UTC +00:00 is not "01-13".
But if I use "%W" format, the result is correct ("52-13").
What is it? Or did I make some mistakes?
With week-based week number (%V) one should use week-based year (%g):
DateTime.parse('Mon, 30 Dec 2013 00:00:00 UTC +00:00').strftime "%V-%g"
#⇒ "01-14"
The cday, cweek and cyear are the methods based on the commercial dates.
commercial: Creates a date object denoting the given week date.
So, the last days of an year can be the same week to the new year's starting days. For example 2013 december last dates and 2014 Jan starting days are of the same week, so the week number of the date 'Mon, 30 Dec 2013 00:00:00 UTC +00:00' comes to the new week of next year after all the weeks of the year are completed.
So,
"Mon, 30 Dec 2013 00:00:00 UTC +00:00".to_date.cweek ==> 1
"Mon, 30 Dec 2013 00:00:00 UTC +00:00".to_date.cwday ==>1 (1st week day of week 1 2014(but date is still of 2013)
"Mon, 30 Dec 2013 00:00:00 UTC +00:00".to_date.cwyear ==> 2014
Those are commercial dates, Now check,
"Mon, 30 Dec 2013 00:00:00 UTC +00:00".to_date.year ==> 2013
This is Normal year.
This has a perfect example
I need this
require 'date'
DateTime.parse "Mon, Dec 27 6:30pm"
to return a DateTime for 6:30pm in the EDT timezone, but it returns one in UTC. How can I get a EST DateTime or convert the UTC one into an EDT DateTime with a 6:30pm value?
OK I'm going to offer an answer to my own question
require 'time'
ENV["TZ"] = "US/Eastern"
Time.parse("Mon, Dec 27 6:30pm").to_datetime
=> #<DateTime: 2011-12-27T18:30:00-05:00 (117884327/48,-5/24,2299161)>
In Rails, this worked nicely for me
DateTime.parse "Mon, Dec 27 6:30pm #{Time.zone}"
It won't work in vanilla Ruby though.
Final answer ;-)
require 'date'
estHoursOffset = -5
estOffset = Rational(estHoursOffset, 24)
date = (DateTime.parse("Mon, Dec 27 6:30pm") - (estHoursOffset/24.0)).new_offset(estOffset)
(or -4 for EDT)
DateTime#change()
You can try using change() after parsing it to alter the timezone offset:
DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: '-0400' )
# => Wed, 27 Dec 2017 18:30:00 -0400
You can also just use the hours:
DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: '-4' )
# => Wed, 27 Dec 2017 18:30:00 -0400
But, be careful, you cannot use an integer:
DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: -4 )
# => Wed, 27 Dec 2017 18:30:00 +0000
If you need to determine the correct offset to use based on a time zone you can do something like this:
offset = ( Time.zone_offset('EDT') / 1.hour ).to_s
# => "-4"
DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: offset )
# => Wed, 27 Dec 2017 18:30:00 -0400
You can also use change() to manually set other parts of the DateTime as well, like setting the hour to noon:
DateTime.parse( "Mon, Dec 27 6:30pm" ).change( offset: '-4', hour: 12 )
# => Wed, 27 Dec 2017 12:00:00 -0400
Be careful with that one because you can see that it's cleared the minutes as well.
Here's the docs for the change() method: http://api.rubyonrails.org/v5.1/classes/DateTime.html#method-i-change
If you're using Rails' ActiveSupport:
"Mon, Dec 27 6:30pm".in_time_zone(-4.hours).to_datetime
# => Mon, 27 Dec 2021 18:30:00 -0400
Time.find_zone(-4.hours).parse("Mon, Dec 27 6:30pm").to_datetime
# => Mon, 27 Dec 2021 18:30:00 -0400
If you want to use the local daylight saving time (DST) rules, you could use:
"Mon, Dec 27 6:30pm".in_time_zone("Eastern Time (US & Canada)")
# => Mon, 27 Dec 2021 18:30:00 EST -05:00
Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Dec 27 6:30pm")
# => Mon, 27 Dec 2021 18:30:00 EST -05:00
Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Dec 27 6:30pm").to_datetime
# => Mon, 27 Dec 2021 18:30:00 -0500
Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Jun 27 6:30pm")
# => Sun, 27 Jun 2021 18:30:00 EDT -04:00
Time.find_zone("Eastern Time (US & Canada)").parse("Mon, Jun 27 6:30pm").to_datetime
# => Sun, 27 Jun 2021 18:30:00 -0400
Time.find_zone("EST5EDT").parse("Mon, Jun 27 6:30pm").to_datetime
# => Sun, 27 Jun 2021 18:30:00 -0400
Notice the date in June, above, is automatically set to EDT (-0400) because this date is in DST, contrary to the December date.
To force EST regardless if date is within DST or not:
Time.find_zone("EST").parse("Mon, Jun 27 6:30pm")
# => Sun, 27 Jun 2021 18:30:00 EST -05:00
Time.find_zone("EST").parse("Mon, Jun 27 6:30pm").to_datetime
# => Sun, 27 Jun 2021 18:30:00 -0500