Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Parsing Timestamp with extra spaces

by htmanning (Friar)
on May 11, 2020 at 23:09 UTC ( [id://11116679]=perlquestion: print w/replies, xml ) Need Help??

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

$timestamp_perl = $dt->strftime("%a %b %e, %Y - %k:%M:%S"); Monks,

I'm trying to parse through a timestamp and set each piece to a variable so I can compare the date. I grab the timestamp out of the database, then compare it to $now to see if I should display certain data. The issue I'm having is if the date number (1-31) is a single digit number, there is an extra space before the actual number and the below doesn't work correctly. This also happens if the time starts with a single digit number. I'm not sure how to solve this. In other words, if the timestamp is Mon May 9, 2020 - 11:11:11 the $this_date var is empty and the $this_year var become the date number (9).

$timestamp = $dt->strftime("%a %b %e, %Y - %k:%M:%S"); #timestamp in +the database like this @timestamp = split (/ /, $timestamp); $this_day = "@ timestamp[0]"; $this_month = "@ timestamp[1]"; $this_date = "@ timestamp[2]"; $this_year = "@ timestamp[3]"; $this_dash = "@ timestamp[4]"; $this_time = "@ timestamp[5]";

Replies are listed 'Best First'.
Re: Parsing Timestamp with extra spaces
by choroba (Cardinal) on May 11, 2020 at 23:20 UTC
    The easiest fix is to split on general whitespace:
    split ' ', $timestamp;

    Update:

    Another way is to use a library that does the parsing for you:

    #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; use Time::Piece; my $timestamp = 'Tue May 9, 2020 - 1:18:19'; my $tp = 'Time::Piece'->strptime($timestamp, '%a %b %d, %Y - %H:%M:%S' +); my $wday = $tp->wdayname; my $month = $tp->monname; my $day = $tp->mday; my $year = $tp->year; my $hours = $tp->hour; my $min = $tp->minute; my $sec = $tp->second; say "wday: $wday."; say "month: $month."; say "day: $day."; say "year: $year."; say "hours: $hours."; say "minutes: $min."; say "seconds: $sec.";

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Parsing Timestamp with extra spaces
by perlfan (Vicar) on May 12, 2020 at 02:16 UTC
    Is the data field in the DB one of date or time? Seems to be the best thing to do is format it in the SELECT you're using so that it can be received as expected.

    https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format (though perhaps you thought of this and it's not in scope atm)

    If the field is not of a date column, then you may wish to fix that with a one time script (after you fix this issue and figure _that_ part out). And make sure whatever is INSERTing the data does so in a way that is recognizable as a valid date to the DB.

Re: Parsing Timestamp with extra spaces (updated)
by AnomalousMonk (Archbishop) on May 12, 2020 at 02:22 UTC

    If you don't want to use a tested module and are willing to roll your own (you may feel you need something very specific), maybe something like:

    c:\@Work\Perl\monks>perl -wMstrict -le "my $timestamp = 'Tue May 9, 2020 - 1:18:19'; ;; my $rx_wday = qr{ (?i) (?: mon | tue | wed | thu | fri | sat | sun) } +xms; my $rx_mon = qr{ [[:alpha:]]+ }xms; my $rx_day = qr{ (?: 3 [01] | [012]? \d) }xms; my $rx_year = qr{ \d{4} }xms; my $rx_24hr = qr{ (?: 2 [0123] | [01]? \d) }xms; my $rx_min = qr{ (?: [0-5]? \d) }xms; my $rx_sec = $rx_min; ;; my $got_date_time = my ($wday, $mon, $day, $year, $hr, $min, $sec) = $timestamp =~ m{ \b ($rx_wday) \s+ ($rx_mon) \s+ ($rx_day) , \s+ ($rx_year) \s+ - \s+ ($rx_24hr) : ($rx_min) : ($rx_sec) \b }xms; ;; die qq{bad timestamp '$timestamp'} unless $got_date_time; ;; print qq{'$wday' '$mon' '$day' '$year' '$hr' '$min' '$sec'}; " 'Tue' 'May' '9' '2020' '1' '18' '19'
    Of course, if you choose this path, a thorough test suite is highly recommended; see Test::More.

    If you roll your own, you can get highly specific. E.g., for month names (untested):
        qr{ [Jj]an (?: uary)? | ... | [Ss]ep (?: t (?: ember)? )? | ... }xms
    One could do something similar for day names.

    Update 1: The  (?: ...) non-capturing group in the definition of  $rx_wday is not needed (but does no harm). What was I thinking?

    Update 2: The  $rx_day regex
        qr{ (?: 3 [01] | [012]? \d)  }xms
    allows invalid day/date numbers of 0 and 00. The regex
        qr{ 3 [01] | [12] \d | 0? [1-9] }xms
    fixes this. Note, however, that the day/date number is not reconciled with the month, so a date of, e.g., Feb 31 will be accepted! (The previous definition of  $rx_day had and some other regex definitions still have unneeded, harmless  (?: ...) non-capturing groups as mentioned in Update 1. The reason for these groups is that I originally wrote all the date component regexes with  \b boundary assertions at the start and end. This necessitated grouping any alternations together due to regex operator precedence issues. I then decided to remove the  \b boundary assertions because the other separator sequences in the main pattern were enough boundary control, but forgot to remove the now-redundant groupings. Encompassing  \b assertions are used in the  m// main match.)


    Give a man a fish:  <%-{-{-{-<

Re: Parsing Timestamp with extra spaces
by Anonymous Monk on May 11, 2020 at 23:19 UTC
    what modules are you using? SSCCE? and does s/\s+/ /g help?
Re: Parsing Timestamp with extra spaces
by johngg (Canon) on May 12, 2020 at 13:45 UTC

    I would just modify any single digits before parsing.

    johngg@shiraz:~/perl/Monks$ perl -Mstrict -Mwarnings -E ' my @dateStrs = ( q{Fri May 8, 2020 - 11:12:13}, q{Fri May 15, 2020 - 14:08:17}, q{Sat May 16, 2020 - 7:31:22}, q{Mon Jun 1, 2020 - 6:24:18}, ); s{(?<=\D)(\d)(?=\D)}{ sprintf q{%02d}, $1 }eg for @dateStrs; say for @dateStrs;' Fri May 08, 2020 - 11:12:13 Fri May 15, 2020 - 14:08:17 Sat May 16, 2020 - 07:31:22 Mon Jun 01, 2020 - 06:24:18

    Perhaps the problem is more complex than stated in the OP but this seems to work.

    Update: A version that copes properly with extra spaces, the first version didn't.

    johngg@shiraz:~/perl/Monks$ perl -Mstrict -Mwarnings -E ' my @dateStrs = ( q{Fri May 8, 2020 - 11:12:13}, q{Fri May 15, 2020 - 14:08:17}, q{Sat May 16, 2020 - 7:31:22}, q{Mon Jun 1, 2020 - 6:24:18}, q{Fri May 8, 2020 - 11:12:13}, q{Fri May 15, 2020 - 14:08:17}, q{Sat May 16, 2020 - 7:31:22}, q{Mon Jun 1, 2020 - 6:24:18}, ); s{(\s+\d)(?=\D)}{ sprintf q{ %02d}, $1 }xeg for @dateStrs; say for @dateStrs;' Fri May 08, 2020 - 11:12:13 Fri May 15, 2020 - 14:08:17 Sat May 16, 2020 - 07:31:22 Mon Jun 01, 2020 - 06:24:18 Fri May 08, 2020 - 11:12:13 Fri May 15, 2020 - 14:08:17 Sat May 16, 2020 - 07:31:22 Mon Jun 01, 2020 - 06:24:18

    Cheers,

    JohnGG

Re: Parsing Timestamp with extra spaces
by Marshall (Canon) on May 14, 2020 at 09:37 UTC
    I have no idea of what you are trying to do.
    Parsing "Mon May 9, 2020 - 11:11:11" is straight-forward.
    use strict; use warnings; my $time_string = 'Mon May 9, 2020 - 11:11:11'; my @timestamp = my ($this_day, $this_month, $this_date, $this_year, $this_time) = split /[\s,-]+/, $time_string; print "$_\n" foreach @timestamp; print "===============\n"; print "Day of week: $this_day\n"; print "Month of year: $this_month\n"; print "Day of Month: $this_date\n"; print "This Year: $this_year\n"; print "This Time: $this_time\n"; __END__ Prints: Mon May 9 2020 11:11:11 =============== Day of week: Mon Month of year: May Day of Month: 9 This Year: 2020 This Time: 11:11:11
    If the timestamp is in a database, this is most likely represented by a single number. I don't understand why this textual representation has to be used. Compare the date/time numbers in the DB directly.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (1)
As of 2024-04-19 00:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found