Ian,
thanks for the detailed report, which is clearly to confirm.
libfaketime internally relies on strptime() to parse the user-specified
timestamp.
On current macOS, your examples work reasonably well in the following
variation:
$ FAKETIME_FMT="%Y-%m-%d %T %z" ./faketime -f '2018-06-26 09:00:03
+0200' gdate -R
Tue, 26 Jun 2018 09:00:03 +0200
$ FAKETIME_FMT="%Y-%m-%d %T %z" ./faketime -f '2018-06-26 09:00:03
+0300' gdate -R
Tue, 26 Jun 2018 08:00:03 +0200
$ FAKETIME_FMT="%Y-%m-%d %T %z" ./faketime -f '2018-06-26 09:00:03
+0400' gdate -R
Tue, 26 Jun 2018 07:00:03 +0200
Whereas on Debian, with the glibc implementation of strptime, we end up
with your results:
$ FAKETIME_FMT="%Y-%m-%d %T %z" ./faketime -f '2018-06-26 09:00:03
+0200' date -R
Tue, 26 Jun 2018 09:00:03 +0200
$ FAKETIME_FMT="%Y-%m-%d %T %z" ./faketime -f '2018-06-26 09:00:03
+0300' date -R
Tue, 26 Jun 2018 09:00:03 +0200
$ FAKETIME_FMT="%Y-%m-%d %T %z" ./faketime -f '2018-06-26 09:00:03
+0400' date -R
Tue, 26 Jun 2018 09:00:03 +0200
Apparently, glibc goes for a new tm->tm_gmtoff field and supports %z
(but not %Z) fully yet. This might give some headaches regarding
cross-platform compatibility, and implementing a completely own parser
(i.e., not using strptime()) does not seem viable, either. So yes, this
needs to be addressed, but will take some time.
As a workaround, you can throw anything at libfaketime what `date` can
interpret, as in
$ LD_PRELOAD=./libfaketime.so.1 FAKETIME_FMT=%s FAKETIME="`date +%s
-d'2018-06-26 09:00:03+0400'`" date -R
Tue, 26 Jun 2018 07:00:03 +0200
Best regards,
Wolfgang