Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

change hour in timestamp

by Anonymous Monk
on Jun 04, 2022 at 21:09 UTC ( [id://11144395]=perlquestion: print w/replies, xml ) Need Help??

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

Hi

I have a date in a string, like:

my $date = 'Sat Jun  4 22:47:31 2022';

This is not a DateTime object. I need to change the timezone of this date by reducing it of 2h. Any suggestion?

Replies are listed 'Best First'.
Re: change hour in timestamp
by 1nickt (Canon) on Jun 04, 2022 at 21:31 UTC

    Hi,

    I suggest to use a parser to parse your string into a DateTime object. I also suggest to handle time zones properly and not just by subtracting a value from the hours. What will happen when you try that and the time is earlier than 02:00 ?

    use strict; use warnings; use feature 'say'; use DateTime::Format::Strptime; my $string = 'Sat Jun 4 01:47:31 2022'; my $parser = DateTime::Format::Strptime->new( pattern => '%a %b %d %T %Y', locale => 'en_US', time_zone => 'America/New_York', on_error => 'croak', ); my $datetime = $parser->parse_datetime($string); $datetime->set_time_zone('America/Denver'); say $datetime->strftime('%a %b %d %T %Y'); __END__

    Hope this helps!


    The way forward always starts with a minimal test.
Re: change hour in timestamp
by johngg (Canon) on Jun 04, 2022 at 22:15 UTC
    The Time::Piece module, along with its associated Time::Seconds module for date calculations, is core.

    johngg@abouriou:~/perl/Monks$ perl -Mstrict -Mwarnings -MTime::Piece - +MTime::Seconds -E 'say q{}; my $date = q{Sat Jun 4 22:47:31 2022}; my $tp = Time::Piece->strptime( $date, q{%a %b %d %T %Y} ); $tp -= ONE_HOUR; $tp -= ONE_HOUR; say $tp->strftime();' Sat, 04 Jun 2022 20:47:31 UTC

    I hope that this is helpful.

    Cheers,

    JohnGG

      G'day JohnGG,

      ++ Upon reading the OP, I immediately thought of Time::Piece; then, after scrolling through the posts, I saw you'd used this already.

      If I may, some minor improvements:

      • Instead of decrementing $tp in two statements, you can do that in one: "$tp -= 2 * ONE_HOUR".
      • Your output has a slightly different format to the OP's input: comma after day and introduced timezone. You can mostly fix that by using the same date format for the input and output.
        Update: On rereading, I also see the month name and day are swapped as are the time and year. The suggested fix handles both of those cases also.
      • If the leading zero on the month nameday is a problem for the OP, you can fix that with sprintf. I added a "$tp += 6 * ONE_DAY" to test that.
        • Checking `man strptime` on my Cygwin platform, I see %d gives a two-digit string, padded with a zero for a single-digit month day. I couldn't find a format for that which doesn't pad with a zero. Assuming I didn't simply miss it, if one exists on another OS, it may not be portable.

      Here's the updated code:

      my $date = q{Sat Jun 4 22:47:31 2022}; my $fmt_t = q{%a %b %d %T %Y}; my $fmt_s = q{%s %s %2d %s %d}; my $tp = Time::Piece->strptime($date, $fmt_t); $tp -= 2 * ONE_HOUR; say sprintf $fmt_s, split q{ }, $tp->strftime($fmt_t); $tp += 6 * ONE_DAY; say sprintf $fmt_s, split q{ }, $tp->strftime($fmt_t);

      which outputs:

      Sat Jun 4 20:47:31 2022 Fri Jun 10 20:47:31 2022

      — Ken

Re: change hour in timestamp
by NERDVANA (Deacon) on Jun 05, 2022 at 14:14 UTC
    My first (and usually last) stop for all date parsing is DateTime::Format::Flexible. It gets this one just fine:

    use DateTime::Format::Flexible; sub date { DateTime::Format::Flexible->parse_datetime(shift); } my $d= date('Sat Jun 4 22:47:31 2022'); $d->set_time_zone('+0200')->set_time_zone('UTC'); print "$d\n";
Re: change hour in timestamp
by LanX (Saint) on Jun 04, 2022 at 21:55 UTC
    > This is not a DateTime object.

    DateTime says

      Parsing Dates

      This module does not parse dates! That means there is no constructor to which you can pass things like "March 3, 1970 12:34".

      Instead, take a look at the various DateTime::Format::* modules on CPAN. These parse all sorts of different date formats, and you're bound to find something that can handle your particular needs.

    I searched around in metacpan and found Date::Parse and the Synopsis seems to do the job well, at least for epoch

    use strict; use warnings; use Data::Dump qw/pp dd/; use Date::Parse; use DateTime; pp my $date = 'Sat Jun 4 22:47:31 2022'; pp my $time = str2time($date); pp my ($ss,$mm,$hh,$day,$month,$year,$zone) = strptime($date); my $dt = DateTime->from_epoch ( epoch => $time, time_zone => 'UTC', # fill in your timezone ); print $dt;

    "Sat Jun 4 22:47:31 2022" 1654375651 (31, 47, 22, 4, 5, 122, undef) 2022-06-04T20:47:31

    Other modules - especially the one suggested by 1nickt - might be better, I just wanted to demonstrate how to solve it by yourself.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

Re: change hour in timestamp
by Anonymous Monk on Jun 05, 2022 at 09:26 UTC

    Thank you for all the interesting answers. Another easy approach to achieve my OP:

    use strict; use warnings; use Time::Piece; my $date = "Sat Jun 4 22:47:31 2022 +0200"; my $fmt = '%a %b %d %T %Y %z'; my $tp = Time::Piece->strptime($date, $fmt); print $tp;

    I agree with the mention that I should work with timezone though.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11144395]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (6)
As of 2024-04-25 10:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found