Mark Stafford wrote:
> I was attempting to write a script something like a world clock to help 
> schedule a task in six time zones.

Are you familiar with the GNU date FAQ entry?  It contains a lot of
useful information concerning date and practical date input formats.

  
https://www.gnu.org/software/coreutils/faq/coreutils-faq.html#The-date-command-is-not-working-right_002e

> Certain zone abbreviations do not support round-trip conversion
...
> # the alias isn't necessary, but it simplifies the demonstration
> alias lax="TZ='America/Los_Angeles' date --date=@1469558444 '+%Y-%m-%d %H:%M 
> %Z'"
> alias syd="TZ='Australia/Sydney' date --date=@1469558444 '+%Y-%m-%d %H:%M %Z'"
> lax
> syd
> date --date "$( lax )"
> date --date "$( syd )"

The GNU date documentation says:

  ‘-d DATESTR’
  ‘--date=DATESTR’
     Display the date and time specified in DATESTR instead of the
     current date and time.  DATESTR can be in almost any common format.
     It can contain month names, time zones, ‘am’ and ‘pm’, ‘yesterday’,
     etc.  For example, ‘--date="2004-02-27 14:19:13.489392193 +0530"’
     specifies the instant of time that is 489,392,193 nanoseconds after
     February 27, 2004 at 2:19:13 PM in a time zone that is 5 hours and
     30 minutes east of UTC.
     Note: input currently must be in locale independent format.  E.g.,
     the LC_TIME=C below is needed to print back the correct date in
     many locales:
          date -d "$(LC_TIME=C date)"
     *Note Date input formats::.

I wish it didn't say "DATESTR can be in almost any common format."
because while it does accept a wide range of input formats it is also
very particular about them too.  That parser and doc is inherited from
the original way-back-when.

But the important part of that documentation is this part:

     Note: input currently must be in locale independent format.  E.g.,
     the LC_TIME=C below is needed to print back the correct date in
     many locales:
          date -d "$(LC_TIME=C date)"
     *Note Date input formats.

And that is the problem with the above.  They are not locale
independent formats.  The problem with locale dependent timezones are
that they are not unambiguous.

> bug symptom:
>   2016-07-26 11:40 PDT
>   2016-07-27 04:40 AEST
>   Tue Jul 26 11:40:00 PDT 2016
>   date: invalid date ‘2016-07-27 04:40 AEST’
> 
> expected behavior:
>   2016-07-26 11:40 PDT
>   2016-07-27 04:40 EST
>   Tue Jul 26 11:40:00 PDT 2016
>   Wed Jul 27 02:40:00 PDT 2016

In order to do what you want to do here it is necessary to use locale
independent date formats.  At least as an input format.  As an output
format other formats may be produced.  But as an input format it needs
to be one of the locale independent formats which are not ambiguous.

I suggest using the numeric timezone using the %z format.  Then it
will work as you expect.  (And while I am there I will compact the
date formats to %F and %T too.)  And note that you were missing the
seconds from your example therefore introducing some error into the
conversion from Unix epoch to timestamp.

Plus I strongly recommend using an unambiguous timestamp output such
as the RFC -R format such as used in mail headers.

  TZ='America/Los_Angeles' date --date=@1469558444 '+%F %T %z'
    2016-07-26 11:40:44 -0700
  date -R --date="$(TZ='America/Los_Angeles' date --date=@1469558444 '+%F %T 
%z')"
    Tue, 26 Jul 2016 12:40:44 -0600

  TZ='Australia/Sydney' date --date=@1469558444 '+%F %T %z'
    2016-07-27 04:40:44 +1000
  date -R --date="$(TZ='Australia/Sydney' date --date=@1469558444 '+%F %T %z')"
    Tue, 26 Jul 2016 12:40:44 -0600

As such although this is a deficiency in the parser it is one that is
documented and has been this way since its introduction into date.
Unless someone steps up to rewrite the parser while also maintaining
backward compatibility with input formats, a non-trivial task, I don't
see that anything will be done about it.

Please see the FAQ for a much longer descrition of various issues
surrounding date input formats.

Bob

Reply via email to