Regexp...::time(3pm)
β¨ Regexp::Common::time β¨
okay bestie, gather round β this is the Regexp::Common::time page from the User Contributed Perl Documentation section (it's a 3pm manpage, iykyk). It's the one that builds regexps for dates and times. Buckle up, it's a long one. π
πΈ NAME πΈ
Regexp::Common::time β date and time regexps, fr fr.
π SYNOPSIS π
use Regexp::Common qw(time);
# Piecemeal, Time::Format-like patterns
$RE{time}{tf}{-pat => 'pattern'}
# Piecemeal, strftime-like patterns
$RE{time}{strftime}{-pat => 'pattern'}
# Match ISO8601-style date/time strings
$RE{time}{iso}
# Match RFC2822-style date/time strings
$RE{time}{mail}
$RE{time}{MAIL} # more-strict matching
# Match informal American date strings
$RE{time}{american}
# Fuzzy date patterns
# YEAR/MONTH/DAY
$RE{time}{ymd} # Most flexible
$RE{time}{YMD} # Strictest (equivalent to y4m2d2)
# Other available patterns: y2md, y4md, y2m2d2, y4m2d2
# MONTH/DAY/YEAR (American style)
$RE{time}{mdy} # Most flexible
$RE{time}{MDY} # Strictest (equivalent to m2d2y4)
# Other available patterns: mdy2, mdy4, m2d2y2, m2d2y4
# DAY/MONTH/YEAR (European style)
$RE{time}{mdy} # Most flexible
$RE{time}{MDY} # Strictest (equivalent to d2m2y4)
# Other available patterns: dmy2, dmy4, d2m2y2, d2m2y4
# Fuzzy time pattern
# HOUR/MINUTE/SECOND
$RE{time}{hms} # H: matches 1 or 2 digits; 12 or 24 hours
# M: matches 2 digits.
# S: matches 2 digits; may be omitted
# May be followed by "a", "am", "p.m.", etc.
π DESCRIPTION π
This module makes regular expressions you can use to parse dates and times. ποΈ For the whole "how do I even use this interface" thing, go read Regexp::Common β it explains the general vibe.
ngl, parsing dates is a dirty business. π Dates show up in one of three orders: year/month/day, month/day/year, or day/month/year. Years can be four digits or two digits (and then you just have to assume stuff about the century, love that for us). Months can be one digit, two digits, a spelled-out name, or a three-letter abbreviation. Day numbers can be one or two digits, and the limits depend on the month β and if it's February, bestie, it even depends on the year. π And on top of all that, everybody uses different punctuation between the pieces. Chaos.
A human clocking "October 21, 2005" and "21.10.05" as the same day? Easy. Getting a program to agree? That's the tricky part. This module is here to make that possible with the least amount of suffering. π
- If you know the exact format of the data you're matching, use one of the specific, piecemeal pattern builders:
tforstrftime. - If you're parsing RFC-2822 mail headers, use the
mailpattern. - If you're parsing informal American dates, use the
americanpattern. - If your input data is a little variable, use one of the fuzzy-matching patterns in the
dmy,mdy, orymdfamilies. - If the data is wildly variable β like, raw user input levels of wild β you should probably give up and use Date::Manip or Date::Parse. π Not me telling you to tap out, but... tap out.
Time values are generally way simpler to parse than date values, thank goodness. There's only one fuzzy pattern for time, and it should cover basically everything you need. β¨
π¦ Time::Format PATTERNS π¦
The Time::Format module uses simple, intuitive strings to describe date and time formats. You can use those same patterns right here. π For the full deets on its format specifiers, go see Time::Format.
Example:
$str = 'Thu November 2, 2005';
$str =~ $RE{time}{tf}{-pat => 'Day Month d, yyyy'};
The patterns can hold more complex regexp expressions too, bestie:
$str =~ $RE{time}{tf}{-pat => '(Weekday|Day) (Month|Mon) d, yyyy'};
Time zone matching (that's the tz format code) tries its hardest to stick to RFC2822 and ISO8601. These time zones get matched:
Z
UT UTC
+hh:mm -hh:mm
+hhmm -hhmm
+hh -hh
GMT EST EDT CST CDT MST MDT PST PDT
π strftime PATTERNS π
The POSIX strftime function is a long-recognized standard for formatting dates and times β iconic, honestly. π This module supports most of its codes for matching; specifically, the aAbBcCDdeHIjmMnprRSTtuUVwWyxXYZ% codes. The %Z format matches time zones exactly the same way as described up in Time::Format PATTERNS above. π«Ά
Also β this module hands you these nonstandard codes:
%_dβ 1- or 2-digit day number (1-31)%_Hβ 1- or 2-digit hour (0-23)%_Iβ 1- or 2-digit hour (1-12)%_mβ 1- or 2-digit month number (1-12)%_Mβ 1- or 2-digit minute (0-59)
Example:
$str = 'Thu November 2, 2005';
$str =~ $RE{time}{strftime}{-pat => '%a %B %_d, %Y'};
And yep, these patterns can hold more complex regexp expressions too:
$str =~ $RE{time}{strftime}{-pat => '(%A|%a)? (%B|%b) ?%_d, %Y'};
β ISO-8601 DATE/TIME MATCHING β
The $RE{time}{iso} pattern matches most (all? π) strings formatted the way ISO-8601 recommends. The canonical ISO-8601 form is:
YYYY-MM-DDTHH:MM:SS
(where "T" is a literal T character, no cap). The $RE{time}{iso} pattern matches that form, plus some variants:
- The date separator character may be a hyphen, a slash (
"/"), a period, or an empty string (omitted). The two date separators must match. - The time separator character may be a colon, a period, a space, or an empty string (omitted). The two time separators must match.
- The date-time separator may be a
T, an underscore, a space, or an empty string (omitted). - Either the date or the time may be omitted. But at least one has to be there. π
- If the date is not omitted, all three of its components must be present.
- If the time is not omitted, all three of its components must be present.
π RFC 2822 MATCHING π
RFC 2822 specifies the format of date/time values in e-mail message headers. In a nutshell, the format is:
dd Mon yyyy hh:mm:ss +zzzz
where dd is the day of the month; Mon is the abbreviated month name (apparently always in English); yyyy is the year; hh:mm:ss is the time; and +zzzz is the time zone, generally given as an offset from GMT.
RFC 2822 also requires the weekday be specified, but this module ignores the weekday β it's redundant and only there for human readability anyway. π
RFC 2822 also requires that older, obsolete date forms be allowed, like alphanumeric time zone codes (e.g. EDT). This module's mail allows for those obsolete date forms. But if you want to match only the proper date forms recommended by RFC 2822, you can use the MAIL pattern instead. β¨
Either way β mail or MAIL β the pattern it generates is very flexible about whitespace. The main differences: with MAIL, two-digit years are not permitted, and the time zone must be four digits preceded by a + or - sign.
πΊπΈ INFORMAL AMERICAN MATCHING πΊπΈ
People in North America β especially in the United States β are fond of writing dates as "Month dd, yyyy", or sometimes with a two-digit year and an apostrophe: "Month dd, 'yy". The american pattern matches this style of date. It allows either a month name or a month abbreviation, and it's chill about commas and whitespace. π
π§ FUZZY PATTERN OVERVIEW π§
Fuzzy date patterns all share these properties, bestie:
- The pattern names are made of the letters
y,m, andd, each optionally followed by a digit (2 formandd; 2 or 4 fory). - If a
yis followed by a 2 or a 4, it must match that many digits. - If a
yhas no trailing digit, it can match either 2 or 4 digits, trying 4 first. - If an
mis followed by a 2, then only two-digit matches for the month are considered, and month names are not matched. - If an
mis not followed by a 2, then the month may be 1 or 2 digits, or a spelled-out name. - Just like for months: if a
dis followed by a 2, then only two-digit matches for the day are considered. - Just like for months: if a
dhas no trailing digit, then the day may be 1 or 2 digits, and a 1-digit match may not have any adjacent digits. - The uppercase
DMY,MDY, andYMDpatterns are synonyms for the strictd2m2y4,m2d2y4, andy4m2d2patterns, respectively. - If a one-digit match is considered for the month, then no adjacent digits are allowed. (e.g.:
"1/23/45"in M/D/Y format has a valid one-digit month match, but"12345"does not. Nor does"91/23/45".) - If a pattern begins with a digitless
d,m, ory, then, in the string being matched, any leading digits will cause the pattern to fail. For example:"012/23/45"will not match$RE{time}{mdy}. However, it will match$RE{time}{m2d2y2}. If you specify an exact pattern by usingm2instead ofm, this module assumes you know what you're doing. π - Likewise, a pattern ending with a digitless
dorywill not match if there are trailing digits in the string.
π FUZZY PATTERN DETAILS π
okay bestie, this is where it gets good β all the actual patterns, one by one, no skips π
π Year-Month-Day order π
$RE{time}{ymd}
"05/4/2" =~ $RE{time}{ymd};
"2005-APR-02" =~ $RE{time}{ymd};
This one is the most flexible of all the numeric-only year/month/day formats β she does the most, periodt. It matches a date shaped like year/month/day, where:
- the year can be 2 or 4 digits π
- the month can be 1 or 2 digits, OR a spelled-out name, OR a name abbreviation
- the day can be 1 or 2 digits
And the year/month/day pieces can be squished right up against each other, or separated by a space, a period, a slash (/), or a hyphen. She's flexible like that π
$RE{time}{y4md}
"2005/4/2" =~ $RE{time}{y4md};
"2005 APR 02" =~ $RE{time}{y4md};
Same energy as $RE{time}{ymd}, except the year is locked to exactly 4 digits. no negotiation β¨
$RE{time}{y4m2d2}
"2005/04/02" =~ $RE{time}{y4m2d2};
Again like $RE{time}{ymd}, but the year is exactly 4 digits and both the month and the day must be exactly 2 digits each. strict queen π
$RE{time}{y2md}
"05/4/2" =~ $RE{time}{y2md};
"05.APR.02" =~ $RE{time}{y2md};
Like $RE{time}{ymd}, but the year is exactly 2 digits. that's it, that's the whole vibe πΈ
$RE{time}{y2m2d2}
"05/04/02" =~ $RE{time}{y2m2d2};
Like $RE{time}{ymd}, but the year is exactly 2 digits and the month and day must each be exactly 2 digits. everyone's on their 2-digit best behavior π«Ά
$RE{time}{YMD}
"2005/04/02" =~ $RE{time}{YMD};
This is just a shorthand for the "canonical" year/month/day format, y4m2d2. iconic abbreviation behavior π
πΊπΈ Month-Day-Year (American) order πΊπΈ
$RE{time}{mdy}$RE{time}{mdy4}$RE{time}{m2d2y4}$RE{time}{mdy2}$RE{time}{m2d2y2}$RE{time}{MDY}
These do exactly what the equivalent year/month/day patterns above do β the only difference is the order the elements show up in. And MDY is a synonym for m2d2y4. same brain, different outfit β¨
πͺπΊ Day-Month-Year (European) order πͺπΊ
$RE{time}{dmy}$RE{time}{dmy4}$RE{time}{d2m2y4}$RE{time}{dmy2}$RE{time}{d2m2y2}$RE{time}{DMY}
Same deal, European edition: these work like the equivalent year/month/day patterns above, and the only difference is element order. DMY is a synonym for d2m2y4. slay across the pond π
β° Time pattern (Hour-minute-second) β°
$RE{time}{hms}
"10:06:12a" =~ /$RE{time}{hms}/;
"9:00 p.m." =~ /$RE{time}{hms}/;
Matches a time value inside a string. here are the rules, bestie, don't skip them:
- The hour must be in the range 0 to 24.
- The minute and second values must be in the range 0 to 59, and must be two digits β meaning they need leading zeroes if they're less than 10. no shortcuts π
- The hour, minute, and second components can be separated by colons (
:), periods, or spaces. - The "seconds" value may be omitted.
- The time may be followed by an "am/pm" indicator, which is one of these exact values:
a am a.m. p pm p.m. A AM A.M. P PM P.M.
- And yes, there may be a space between the time and the am/pm indicator. she's chill about the gap π
π CAPTURES (-keep) π
Under -keep, the tf and strftime patterns capture the entire match as $1, plus one capture variable for each format specifier. BUT β huge but β if your pattern contains any parentheses, tf and strftime will not capture anything extra beyond what you yourself specified, -keep or not. In other words: if you use parentheses, you are responsible for all the capturing. it's giving "you built this, you own this" π
The iso pattern captures:
$1β the entire match$2β the year$3β the month$4β the day$5β the hour$6β the minute$7β the second
Heads up: the year, month, and day ($2, $3, and $4) will be undef if the matched string contains only a time value (like 12:34:56). And the hour, minute, and second ($5, $6, and $7) will be undef if the matched string contains only a date value (like 2005-01-23). she gives you what exists, and nothing else π
The mail and MAIL patterns capture:
$1β the entire match$2β the day$3β the month$4β the year$5β the hour$6β the minute$7β the second$8β the time zone
The american pattern captures:
$1β the entire match$2β the month$3β the day$4β the year
The fuzzy y/m/d patterns capture:
$1β the entire match$2β the year$3β the month$4β the day
The fuzzy m/d/y patterns capture:
$1β the entire match$2β the month$3β the day$4β the year
The fuzzy d/m/y patterns capture:
$1β the entire match$2β the day$3β the month$4β the year
The fuzzy h/m/s pattern captures:
$1β the entire match$2β the hour$3β the minute$4β the second (undefif omitted)$5β the am/pm indicator (undefif omitted)
β¨ EXAMPLES β¨
okay here's where it all clicks, bestie, watch this π
# Typical usage: parsing a data record.
#
$rec = "blah blah 2005/10/21 blah blarrrrrgh";
@date = $rec =~ m{^blah blah $RE{time}{YMD}{-keep}};
# or
@date = $rec =~ m{^blah blah $RE{time}{tf}{-pat=>'yyyy/mm/dd'}{-keep}};
# or
@date = $rec =~ m{^blah blah $RE{time}{strftime}{-pat=>'%Y/%m/%d'}{-keep}};
and now the chaotic version, where the format is not your friend:
# Typical usage: parsing variable-format data.
#
use Time::Normalize;
$record = "10-SEP-2005";
# This block tries M-D-Y first, then D-M-Y, then Y-M-D
my $matched;
foreach my $pattern (qw(mdy dmy ymd))
{
@values = $record =~ /^$RE{time}{$pattern}{-keep}/
or next;
$matched = $pattern;
}
if ($matched)
{
eval{ ($year, $month, $day) = normalize_rct($matched, @values) };
if ($@)
{
.... # handle erroneous data
}
}
else
{
.... # no match
}
#
# $day is now 10; $month is now 09; $year is now 2005.
and the time examples, because we do those too π
# Time examples
$time = '9:10pm';
@time_data = $time =~ /$RE{time}{hms}{-keep}/;
# captures '9:10pm', '9', '10', undef, 'pm'
@time_data = $time =~ /$RE{time}{tf}{-pat => '(h):(mm)(:ss)?(am)?'}{-keep}/;
# captures '9', '10', undef, 'pm'
π¦ EXPORTS π¦
This module exports no symbols to the caller's namespace. she minds her own business, respectfully π
π SEE ALSO π
ngl bestie, it's not enough that the date regexps can match a bunch of formats β after that you still have to parse those matched data values and translate them into useful values. So: the Time::Normalize module is highly recommended for doing that repetitive, error-prone task. let it carry the emotional labor for you π«Ά
π οΈ REQUIREMENTS π οΈ
Requires Regexp::Common, of course. obviously. it's the whole point π
If POSIX and I18N::Langinfo are available, this module will use them; otherwise, it falls back to hardcoded English values for month and weekday names. improvising, but in English πΈ
Test::More is required for the test suite. gotta test, no cap β¨
π AUTHOR π
Eric J. Roode, ROODE -at- cpan -dot- org
β LICENSE AND COPYRIGHT β
Copyright (c) 2005-2008 by Eric J. Roode, ROODE -at- cpan -dot- org
All rights reserved.
To avoid my spam filter, please include "Perl", "module", or this module's name in the message's subject line, and/or GPG-sign your message. (he's asking nicely, bestie, just do it π)
This module is copyrighted only to ensure proper attribution of authorship and to ensure that it remains available to all. This module is free, open-source software. This module may be freely used for any purpose β commercial, public, or private β provided that proper credit is given, and that no more-restrictive license is applied to derivative (not dependent) works. generous king behavior π
Substantial efforts have been made to ensure that this software meets high quality standards; however, no guarantee can be made that there are no undiscovered bugs, and no warranty is made as to suitability to any given use, including merchantability. And then the absolutely unhinged disclaimer, which I am legally obligated to relay verbatim in spirit: should this module cause your house to burn down, your dog to collapse, your heart-lung machine to fail, your spouse to desert you, or George Bush to be re-elected, the author can offer only his sincere sympathy and apologies, and promises to endeavor to improve the software. ππ not the heart-lung machineβ
aaaand that's a wrap on Regexp::time(3pm), bestie!! this page came from the Perl v5.36.0 docs, dated 2022-12-06, in the User Contributed Perl Documentation collection. you now know more about date regexps than 99% of people alive. go forth and parse responsibly π¦β¨π
π¦ where this page comes from
- debian bookworm: libregexp-common-time-perl 0.16-2 Β· other
- debian trixie: libregexp-common-time-perl 0.16-2 Β· other
- ubuntu noble: libregexp-common-time-perl 0.16-2 Β· other
- ubuntu resolute: libregexp-common-time-perl 0.16-2 Β· other
- ubuntu stonking: libregexp-common-time-perl 0.16-2 Β· other
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms