isync has asked for the wisdom of the Perl Monks concerning the following question:

As most perlmonks will know, ctime, mtime and atime returned by stat() need to be taken with a bit of salt, namely a timezone offset flag.

Doing stat <file> outside of perl, on the command line, I will get stuff like:
Access: 2010-02-09 15:51:56.500000000 +0100
Modify: 2008-10-09 17:16:33.750000000 +0200
Change: 2008-10-09 17:16:34.265625000 +0200
Inside Perl, Perl handles these offsets automagically, so when I feed the stat() epoch of let's say $mtime to localtime() I will get a timezone corrected date/time. Same for gmtime(), where I get GMT values.

But where does this magic come from?
The epoch I get from stat() doesn't hold it. How can I get a timezone corrected, for example GMT epoch without doing stat()->$mtime->gmtime()->convert humand-readable back to epoch?

Replies are listed 'Best First'.
Re: stat() and time-zone-offsets?
by ikegami (Patriarch) on Jun 17, 2010 at 02:25 UTC

    This should be documented in localtime, but POSIX's tzset updates the timezone used by localtime. See the documentation for the underyling C library function.

    It's not really designed as a tool to render times in other arbitrary time zones. You may want to use a module such as DateTime for that.

    $ perl -MDateTime -le' my $dt = DateTime->from_epoch( epoch => 1234567890 ); for ("America/New_York", "Europe/Rome") { $dt->set_time_zone($_); print $dt->strftime("%Y/%m/%d %H:%M:%S"); } ' 2009/02/13 18:31:30 2009/02/14 00:31:30
Re: stat() and time-zone-offsets?
by jwkrahn (Abbot) on Jun 17, 2010 at 01:53 UTC
    Perl handles these offsets automagically
    ...
    But where does this magic come from?

    Actually, perl just hands the epoch time (Coordinated Universal Time (UTC)) off to the localtime(3) function in the C library which handles the "magic".

    How can I get a timezone corrected

    You should probably have a look at the time zone functions in the POSIX module.

Re: stat() and time-zone-offsets?
by bluescreen (Friar) on Jun 17, 2010 at 02:40 UTC

    What you get from stat is epoch GMT already, so to get GMT you don't need to do anything.

    If you want to get the epoc in your local timezone you need to do a trick to get the difference from GMT to your timezone as described in Re: Re: How to get TZ difference? and then apply that difference to the value you get from stat()

Re: stat() and time-zone-offsets?
by isync (Hermit) on Jun 17, 2010 at 10:43 UTC
    mmhh... could be my memory plays tricks on me, but what brought me to thinking that the mtime/epoch isn't timezone corrected were a number of stats() where the time was skewed against what Windows or the CLI stat told me.

    Now thinking again, I tend to accept stat() returns GMT epoch.
    Still, are you sure this is consistent across *nix and Windows. Does a Perl stat() on Windows/NTFS return GMT epoch - really?

      Epoch time in unix is the number of seconds since the beginning of Jan 1st, 1970 GMT (or UTC? It's basically the same thing as far as most people are concerned).

      Still, are you sure this is consistent across *nix and Windows.

      Yes, stat returns unix epoch times on Windows. But read on.

      When I looked at the cloned file's metadata via Windows's file properties it showed a 1 hour time offset.

      Explorer shows the timestamp using the current local time zone. Sounds normal, but there's a catch. It views timezones as offsets from GMT, not slices of geograghy, so EST and EDT are two different time zones to it.

      If I created a file at

      2010-01-01 18:00:00 (local time)

      and if checked the creation date today, Explorer would show it as being created at

      2010-01-01 17:00:00 (EDT)
      rather than
      2010-01-01 18:00:00 (America/New_York)

      I don't know if that's a problem in Explorer, or a problem with the OS itself. It could even be specific to the file system. This could have an effect on stat.

      Still, are you sure this is consistent across *nix and Windows. Does a Perl stat() on Windows/NTFS return GMT epoch - really?

      Yes, I think so

      #!/usr/bin/perl -- use strict; use warnings; use autodie 2.10; use File::Spec; Main(@ARGV); exit(0); sub Main { my $file = File::Spec->rel2abs(__FILE__) . '-testfile'; open my ($fh), '>', $file; close $fh; print " gmtime ", scalar gmtime, "\n"; print " stat gmtime ", scalar gmtime( ( stat $file )[10] ), "\n" +; print " localtime ", scalar localtime, "\n"; print "stat localtime ", scalar localtime( ( stat $file )[10] ), " +\n"; unlink $file; } ## end sub Main __END__
      gmtime Thu Jun 17 11:36:22 2010 stat gmtime Thu Jun 17 11:36:22 2010 localtime Thu Jun 17 04:36:22 2010 stat localtime Thu Jun 17 04:36:22 2010
Re: stat() and time-zone-offsets?
by isync (Hermit) on Jun 19, 2010 at 01:21 UTC
    I think, Ikegami, you've found the golden nugget!
    Thanks everyone for donating time thinking about (and solving) my problem!