How to parse timezone with date - linux

How do we get the date utility to parse the timezone strings?
$>date -d "2018-02-21T02:22:33.221" "+%Y-%m-%dT%H:%M:%S.%3N %Z"
2018-02-20T14:22:33.221 EST
But
$>date -d "2018-02-21T02:22:33.221 EST" "+%Y-%m-%dT%H:%M:%S.%3N %Z"
date: invalid date `2018-02-21T02:22:33.221 EST'
This the local info:
$>uname -r
2.6.32-696.13.2.el6.x86_64
$>date
Tue Jan 16 09:58:52 EST 2018
$>date --version
date (GNU coreutils) 8.4
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by David MacKenzie.

ISO8601 allows you to replace T with space. Just do it, and your command will work fine:
# date -d "2018-02-21T02:22:33.221 EST" "+%Y-%m-%dT%H:%M:%S.%3N %Z"
date: invalid date `2018-02-21T02:22:33.221 EST'
but:
# date -d "2018-02-21 02:22:33.221 EST" "+%Y-%m-%d %H:%M:%S.%3N %Z"
2018-02-21 10:22:33.221 MSK

date -d is not the reverse of date +format, it can only accept some string from man date
-d, --date=STRING
display time described by STRING, not `now'
DATE STRING
The --date=STRING is a mostly free format human readable date string such as "Sun, 29 Feb 2004 16:21:42 -0800" or
"2004-02-29 16:21:42" or even "next Thursday". A date string may contain items indicating calendar date, time of day,
time zone, day of week, relative time, relative date, and numbers. An empty string indicates the beginning of the day.
The date string format is more complex than is easily documented here but is fully described in the info documentation.

Related

Converting date in a different timezone with `date`

I am trying to convert dates from different timezones with UNIX date (I am on Ubuntu 20.04).
With current date, it works well:
$ date
dim. 12 déc. 2021 11:59:16 CET
$ TZ=Pacific/Tahiti date
dim. 12 déc. 2021 00:59:32 -10
But when I am working with a string, it fails:
$ export testdate="2021/10/28 17:47:26"
$ date -d "$test"
jeu. 28 oct. 2021 17:47:26 CEST
$ TZ=Pacific/Tahiti date -d "$test"
jeu. 28 oct. 2021 17:47:26 -10
as I am expecting:
jeu 28 oct. 2021 05:47:26 -10
I don't understand why I don't get the proper shift. And of course if I try with a date and time where the day should also change, it doesn't work either:
$ export test="2021/10/28 7:47:26"
$ date -d "$test"
jeu. 28 oct. 2021 07:47:26 CEST
$ TZ=Pacific/Tahiti date -d "$test" "+%F %T %Z"
2021-10-28 07:47:26 -10
while I am expecting:
mer 27 oct. 2021 19:47:26 -10
why I don't get the proper shift
test="2021/10/28 17:47:26"
Is a date in unknown timezone. No one knows what timezone it is in, what the daylight is. GNU date tries to "guess" what offset you meant, it generally traverses TZ database for current timezone and just picks the first offset that matches. Also, specifying timezone is not enough to know what daylight it is, you have to be specific.
Also, because of the daylight time you can "go back" in time, it's now known what the offset to UTC is even when you know the timezone.
Also, you don't have to export it - date does not care about test environment variable.
Converting date in a different timezone with date
If the input is in UTC, tell date that.
$ LC_ALL=C TZ=Pacific/Tahiti date -d "2021/10/28 17:47:26 UTC"
Thu Oct 28 07:47:26 -10 2021
If the input is with any other offset, tell date that.
$ LC_ALL=C TZ=Pacific/Tahiti date -d "2021/10/28 17:47:26 CEST"
Thu Oct 28 05:47:26 -10 2021
Te parsing of GNU date of input format is generally a mystery. The documentation lists 2004-02-29 16:21:42 format as an example input, so I recommend that format. If you want to be exact, I recommend strptime from dateutils (or a real programming language).
One simple way is to convert time first to epoch time :
test="2021/10/28 17:47:26"
TZ=Pacific/Tahiti date -d #$(date -d "$test" +%s)
date -d "$test" +%s converts local time to epoch time.
TZ=Pacific/Tahiti date -d #$(date -d "$test" +%s) prints Tahiti time from epoch time.
I'm not fully confident, but i get the impression you're looking the following syntax:
LC_TIME="es_ES.UTF8" TZ="America/New_York" date --date='TZ="Europe/Amsterdam" 2021/10/28 17:47:26' "+%A %F %T %B"
That takes a predefined datetime (interpreted as being local to Amsterdam), adjusts the datetime (based on the time difference) to New York-time at that same moment; Then it prints that result with Spanish names for the months/weekdays (provided that language' locale is present on your system).

How to convert to / get RFC822 date in bash/linux?

Looking at date's man page, I couldn't find a standard way to convert to rfc822 (eg: from unix timestamp). I took a brief look at the spec, but I don't know enough about the subject matter to get the format right. Is there a easy way to convert to rfc822 with standard linux terminal tools?
According to man 1 date:
-R, --rfc-email
output date and time in RFC 5322 format.
Example: Mon, 14 Aug 2006 02:34:56 -0600
And it looks like RFC5322:
[...] is a revision of Request For Comments (RFC) 2822, which itself superseded
Request For Comments (RFC) 822 [...]
Short answer use date -R (and -d #<unix> for the unix timestamp). For example, in my machine just now:
$ date -R
Mon, 11 Sep 2017 20:41:30 +0200
$ date -R -d #1505155314
Mon, 11 Sep 2017 20:41:54 +0200

Convert timestamp in linux

I have a date represented as 1231533845
I understand that is supposed to be Fri Jan 9 15:44:05 EST 2009
And that on OSX it can be decoded with:
date -j -f %s 1231533845
What's the equivalent command on linux?
You will use the date function, but with the option -d
date -d #1231533845

How can I use date command in Linux to read ANSI date

ANSI date numbers starts from January 1st 1601 (day 1).
So how to get the following to work in a bash command in Linux?
I want:
# ANSI / UNIX epoch delta is 134774 days
$ date -ud ‘1601 -01 -01 + 134774 days ’ +%F
1970 -01 -01
But I get
date: invalid date '1601-01-01+134774 days'
To answer my own question as I meanwhile found this site: https://unix.stackexchange.com/questions/7688/date-years-prior-to-1901-are-treated-as-invalid
It's because I'm on a 32-bit machine.
date -ud '1901-12-14 + 24855 days' +%F
will give
1970-01-01

Bash date command invalid date

In linux bash when I enter date -d "1986-01-01" it shows error
date: invalid date "1986-01-01"
when date -d "1986-01-02" it works
when date -d "1987-01-01" it also works
Why date -d "1986-01-01" shows error in Linux Bash shell.
I am using Fedora 16
Nepal changed its timezone at the beginning of 1986. The following table is copied from the tzdata package:
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Kathmandu 5:41:16 - LMT 1920
5:30 - IST 1986
5:45 - NPT # Nepal Time
That means that on Jan 1 1986 the time from 00:00:00 to 00:14:59 is not valid. The following two commands show, that the first day of 1986 started with 00:15:00:
$ TZ=Asia/Kathmandu date -d '1985-12-31 23:59:59' '+%s'
504901799
$ TZ=Asia/Kathmandu date -d '1986-01-01 00:15:00' '+%s'
504901800
So the error message of date is correct. The date is invalid in this timezone. I am not sure what you are doing with the result of this command. However, you can try to use UTC because all dates are valid and unambiguous in UTC:
$ TZ=UTC date -d '1986-01-01'
Wed Jan 1 00:00:00 UTC 1986
I think you are using alphabet "O" in upper case instead of number "0" in the command :)

Resources