NAME
Time::Str - Parse and format date/time strings in multiple standard formats
SYNOPSIS
use Time::Str qw( str2time str2date time2str );
# Parse to Unix timestamp
my $time = str2time('2024-12-24T15:30:45Z');
my $time = str2time('Mon, 24 Dec 2012 15:30:45 +0100', format => 'RFC2822');
# Parse to components
my %date = str2date('2024-12-24T15:30:45.500+01:00');
# (year => 2024, month => 12, day => 24, hour => 15,
# minute => 30, second => 45, nanosecond => 500000000,
# tz_offset => 60)
# Format Unix timestamp
my $str = time2str(1735052445);
# '2024-12-24T15:30:45Z'
my $str = time2str(1735052445, format => 'RFC2822', offset => 60);
# 'Tue, 24 Dec 2024 16:30:45 +0100'
DESCRIPTION
Time::Str parses date/time strings from various standard formats into Unix timestamps or components, and formats Unix timestamps back into strings.
Supported standards include ISO 8601, RFC 3339, RFC 2822, RFC 2616 (HTTP), ISO 9075 (SQL), ASN.1, and others. A permissive Generic parser handles most real-world date/time representations that can be parsed without ambiguity.
FUNCTIONS
str2time
my $time = str2time($string);
my $time = str2time($string, format => $format);
my $time = str2time($string, format => $format, precision => $precision);
my $time = str2time($string, format => 'ASN1UT', pivot_year => 2000);
Parses a date/time string and returns a Unix timestamp (seconds since 1970-01-01T00:00:00Z). The timestamp may include fractional seconds.
The input must include a UTC designator (Z, UTC, GMT) or a numeric timezone offset. Strings with only an unresolved timezone abbreviation (e.g., EST, IST) will croak. See "TIMEZONE ABBREVIATIONS".
Parameters
$string(required)The date/time string to parse.
format(optional, default:'RFC3339')The format specification. See "SUPPORTED FORMATS".
precision(optional, default: 6 or 9 depending on float size)Number of decimal places to preserve for fractional seconds (0-9). Fractional digits beyond the specified precision are truncated, not rounded. See "PRECISION HANDLING".
pivot_year(optional, default: 1950)For formats with two-digit years (
ASN1UT, RFC 850 withinRFC2616), sets the pivot year for century expansion. Two-digit years less than(pivot_year % 100)map to the next century; others map to the current century.With the default pivot of 1950:
49becomes 2049,50becomes 1950,99becomes 1999.
Returns
A numeric Unix timestamp, possibly with a fractional part. The supported range is 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z.
Errors
Croaks if:
The string cannot be parsed in the specified format
Date or time components are out of valid ranges
No timezone offset or UTC designator is present
A named parameter is unknown or out of range
Examples
# RFC 3339 (default)
my $t = str2time('2024-12-24T15:30:45Z');
# 1735052445
my $t = str2time('2024-12-24T15:30:45.500+01:00');
# 1735048845.5
# RFC 2822
my $t = str2time('Mon, 24 Dec 2012 15:30:45 +0100',
format => 'RFC2822');
# HTTP
my $t = str2time('Mon, 24 Dec 2012 15:30:45 GMT',
format => 'RFC2616');
# Precision (truncation, not rounding)
my $t = str2time('2024-12-24T15:30:45.123456789Z', precision => 3);
# 1735052445.123
my $t = str2time('2024-12-24T15:30:45.999999Z', precision => 3);
# 1735052445.999 (NOT 1735052446.000)
str2date
my %date = str2date($string);
my %date = str2date($string, format => $format);
my %date = str2date($string, format => 'ASN1UT', pivot_year => 2000);
Parses a date/time string and returns the parsed components. Unlike str2time, this does not require a timezone and preserves all parsed information without converting to a timestamp.
Parameters
$string(required)The date/time string to parse.
format(optional, default:'RFC3339')The format specification. See "SUPPORTED FORMATS".
pivot_year(optional, default: 1950)For formats with two-digit years, sets the pivot year for century expansion.
Returns
In list context, returns key-value pairs. In scalar context, returns a hash reference.
All values are numeric except tz_utc, tz_abbrev, and tz_annotation. The following components may be present:
year- Four-digit year (1-9999)month- Month (1-12)day- Day of month (1-31)hour- Hour in 24-hour format (0-23)minute- Minute (0-59)second- Second (0-60; 60 allows for leap seconds)nanosecond- Fractional seconds as nanoseconds (0-999999999)tz_offset- Timezone offset in minutes from UTC (e.g., 60 for +01:00). Present when a numeric offset or UTC designator was parsed.tz_utc- The UTC designator (Z,UTC,GMT) if one was present. When followed by a numeric offset (e.g.,UTC+05:30),tz_offsetreflects that offset rather than zero.tz_abbrev- The timezone abbreviation as it appeared in the input, if present and not a UTC designator.tz_offsetwill not be present whentz_abbrevis set. See "TIMEZONE ABBREVIATIONS".tz_annotation- Bracketed timezone tag from the input, if present (RFC 9557 IXDTF or JavaZoneIdformat, e.g.,[Europe/Stockholm]). Informational only; does not affecttz_offset.
Errors
Croaks if:
The string cannot be parsed in the specified format
Date or time components are out of valid ranges
A named parameter is unknown or out of range
Examples
# Full RFC 3339 timestamp
my %d = str2date('2024-12-24T15:30:45.500+01:00');
# (year => 2024,
# month => 12,
# day => 24,
# hour => 15,
# minute => 30,
# second => 45,
# nanosecond => 500000000,
# tz_offset => 60)
# Partial dates
my %d = str2date('2024-12-24', format => 'W3CDTF');
# (year => 2024, month => 12, day => 24)
my %d = str2date('2024', format => 'W3CDTF');
# (year => 2024)
# 12-hour clock
my %d = str2date('December 24, 2024, 3:30 PM', format => 'generic');
# (..., hour => 15)
# Two-digit year
my %d = str2date('Monday, 24-Dec-50 15:30:45 GMT',
format => 'RFC2616');
# (year => 1950, ...)
# Two-digit year with custom pivot
my %d = str2date('Monday, 24-Dec-50 15:30:45 GMT',
format => 'RFC2616', pivot_year => 1970);
# (year => 2050, ...)
# UTC designator
my %d = str2date('24 Dec 2012 15:30:45 GMT', format => 'RFC2822');
# (..., tz_utc => 'GMT', tz_offset => 0)
# UTC designator with offset
my %d = str2date('December 24, 2024 at 3:30 pm UTC+05:30',
format => 'generic');
# (..., tz_utc => 'UTC', tz_offset => 330)
# Timezone abbreviation (unresolved)
my %d = str2date('24 Dec 2012 15:30:45 IST', format => 'RFC2822');
# (..., tz_abbrev => 'IST')
# RFC 9557 annotation
my %d = str2date('2024-12-24T15:30:45.500+01:00[Europe/Stockholm]',
format => 'generic');
# (..., tz_offset => 60, tz_annotation => '[Europe/Stockholm]')
time2str
my $str = time2str($time);
my $str = time2str($time, format => $format);
my $str = time2str($time, format => $format, offset => $offset);
my $str = time2str($time, nanosecond => $ns, precision => $prec);
Formats a Unix timestamp into a date/time string.
Parameters
$time(required)Unix timestamp (seconds since 1970-01-01T00:00:00Z). May be an integer or floating-point number. Supported range: 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z.
format(optional, default:'RFC3339')The output format. See "SUPPORTED FORMATS". Not all formats support fractional seconds or timezone offsets.
offset(optional, default: 0)Timezone offset in minutes from UTC. Positive is east, negative is west. Valid range: -1439 to +1439 (-23:59 to +23:59).
precision(optional)Number of decimal places for fractional seconds (0-9). Fractional seconds are rounded to this precision, which may carry into the seconds field (e.g., rounding
.999at precision 0 yields the next whole second).When omitted and the timestamp has fractional seconds, precision is auto-detected: 3 if the fractional part is divisible by 0.001, 6 if divisible by 0.000001, or 9 otherwise. When specified as 0, fractional seconds are omitted after rounding.
See "PRECISION HANDLING".
nanosecond(optional)Explicit nanosecond value (0-999999999) for fractional seconds. Overrides any fractional part of
$timeand bypasses rounding. Use this for exact control over fractional output or to preserve nanosecond precision that floating-point cannot represent. Can be combined withprecisionto control zero-padding.
Returns
A formatted date/time string.
Errors
Croaks if:
$timeis outside the supported rangeA named parameter is unknown or out of range
Examples
# RFC 3339 (default)
my $str = time2str(1735052445);
# '2024-12-24T15:30:45Z'
# Timezone offset
my $str = time2str(1735052445, offset => 60);
# '2024-12-24T16:30:45+01:00'
# Fractional seconds (auto-detected precision)
my $str = time2str(1735052445.123456);
# '2024-12-24T15:30:45.123456Z'
# Explicit precision (rounded)
my $str = time2str(1735052445.123456, precision => 3);
# '2024-12-24T15:30:45.123Z'
# Rounding carries into seconds
my $str = time2str(1735052445.999999, precision => 3);
# '2024-12-24T15:30:46.000Z'
# Nanosecond override (no rounding)
my $str = time2str(1735052445, nanosecond => 500_000_000, precision => 9);
# '2024-12-24T15:30:45.500000000Z'
# Zero-padding with nanosecond
my $str = time2str(1735052445, nanosecond => 0, precision => 3);
# '2024-12-24T15:30:45.000Z'
# RFC 2822
my $str = time2str(1735052445, format => 'RFC2822', offset => 60);
# 'Tue, 24 Dec 2024 16:30:45 +0100'
# HTTP (always GMT)
my $str = time2str(1735052445, format => 'RFC2616');
# 'Tue, 24 Dec 2024 15:30:45 GMT'
# SQL with timezone
my $str = time2str(1735052445.5, format => 'ISO9075', offset => 60);
# '2024-12-24 16:30:45.500 +01:00'
# Common Log Format
my $str = time2str(1735052445, format => 'CLF', offset => 60);
# '24/Dec/2024:16:30:45 +0100'
PRECISION HANDLING
The module handles fractional seconds differently when parsing versus formatting.
Parsing (str2time)
Fractional seconds beyond the specified precision are truncated, not rounded. This preserves the exact digits provided in the input up to the requested precision:
str2time('2024-12-24T15:30:45.123456Z', precision => 3)
# Returns: 1735052445.123 (digits beyond 3rd truncated)
str2time('2024-12-24T15:30:45.999999Z', precision => 3)
# Returns: 1735052445.999 (NOT .000 of next second)
Note: str2date does not accept a precision parameter. It always preserves fractional seconds at full nanosecond resolution in the nanosecond component.
Formatting (time2str)
Fractional seconds are rounded to the specified precision. Rounding prevents floating-point artifacts from appearing in formatted output:
time2str(1735052445.123456, precision => 3)
# '2024-12-24T15:30:45.123Z'
time2str(1735052445.999999, precision => 3)
# '2024-12-24T15:30:46.000Z' (rounds up to next second)
time2str(1735052445.999999, precision => 0)
# '2024-12-24T15:30:46Z' (rounds up, fraction omitted)
Bypassing Rounding
The nanosecond parameter overrides the fractional part of $time and is not subject to rounding, giving exact control over the output:
time2str(1735052445, nanosecond => 999_999_000, precision => 6)
# '2024-12-24T15:30:45.999999Z' (exact, no rounding)
time2str(1735052445, nanosecond => 0)
# '2024-12-24T15:30:45Z' (no fractional part)
FLOATING-POINT PRECISION
Perl typically uses IEEE 754 double-precision (64-bit) floating-point, providing approximately 15-17 significant decimal digits shared between the integer and fractional parts of a number.
Implications for Timestamps
Whole seconds are always represented exactly within the supported date range (0001-01-01 to 9999-12-31). Fractional precision depends on the magnitude of the timestamp:
Millisecond precision (
precision => 3) is exact and stable across the entire supported date range.Microsecond precision (
precision => 6) is reliable for timestamps within roughly ±140 years of the Unix epoch (1830-2110). Beyond this range, values may shift by ±1 microsecond due to floating-point spacing.Nanosecond precision cannot be represented faithfully in a floating-point timestamp. Use the
nanosecondparameter for exact sub-microsecond values.
Default Precision
When time2str formats a timestamp with fractional seconds and neither precision nor nanosecond is specified, it uses a system-dependent default determined at compile time:
6 decimal places on standard 64-bit double-precision systems
9 decimal places on platforms with extended floating-point (e.g., long double)
This default prevents spurious trailing digits caused by floating-point representation. For explicit control, always specify precision or nanosecond.
SUPPORTED FORMATS
The following format specifiers are recognized (case-insensitive). The default format is RFC3339.
ANSIC (alias: ctime)
ANSI C asctime() / ctime() format.
DDD MMM (_D|DD) HH:MM:SS YYYY
Where _D is a space-padded single-digit day.
Parsing:
Mon Dec 1 03:04:05 2024
Tue Dec 24 15:30:45 2024
Formatting:
time2str(1735052445, format => 'ANSIC')
# 'Tue Dec 24 15:30:45 2024'
Limitations: Always UTC. Fractional seconds and timezone offsets are not supported; the offset parameter is ignored.
ASN1GT
ASN.1 GeneralizedTime as defined in ITU-T X.680.
YYYYMMDDhh[mm[ss]][(.|,)fraction][Z|±hh[mm]]
Parsing:
Hours are required; minutes and seconds are optional. The fractional part may use a period or comma and applies to the least significant time component present. The timezone designator is optional.
2024122415 # hour only, no timezone
2024122415Z # hour only, UTC
2024122415,5Z # decimal hour (30 minutes)
201212241530Z # hour and minute
201212241530,5Z # decimal minute (30 seconds)
20121224153045 # full time, no timezone
20121224153045Z # full time, UTC
20121224153045.500Z # with fractional seconds
20121224153045,123456789Z # nanoseconds, comma separator
20121224153045+0100 # with numeric offset
Timezone offset format: ±HHMM or ±HH
Formatting:
time2str(1735052445, format => 'ASN1GT')
# '20241224153045Z'
time2str(1735052445, format => 'ASN1GT', precision => 3)
# '20241224153045.500Z'
time2str(1735052445, format => 'ASN1GT', offset => 60)
# '20241224163045+0100'
Limitations: Formatting always outputs hours, minutes, and seconds. Decimal hours and decimal minutes are not produced.
ASN1UT
ASN.1 UTCTime as defined in ITU-T X.680.
YYMMDDhhmm[ss](Z|±hhmm)
Parsing:
Two-digit year; seconds are optional. A timezone designator is required.
9412211010Z # without seconds
241224153045Z # with seconds
241224153045+0100 # with numeric offset
Timezone offset format: ±HHMM
Formatting:
time2str(1735052445, format => 'ASN1UT')
# '241224153045Z'
time2str(1735052445, format => 'ASN1UT', offset => 60)
# '241224163045+0100'
Limitations: Fractional seconds are not supported.
CLF
Common Log Format.
DD/MMM/YYYY:HH:MM:SS[.fraction] ±HHMM
Parsing:
24/Dec/2024:15:30:45 +0100
24/Dec/2024:15:30:45.500 +0100
24/Dec/2024:15:30:45.123456789 -0500
Timezone offset format: ±HHMM
Formatting:
time2str(1735052445, format => 'CLF')
# '24/Dec/2024:15:30:45 +0000'
time2str(1735052445, format => 'CLF', offset => 60)
# '24/Dec/2024:16:30:45 +0100'
time2str(1735052445.5, format => 'CLF', precision => 3, offset => 60)
# '24/Dec/2024:16:30:45.500 +0100'
Generic
A permissive parser that accepts a wide variety of real-world date/time representations, restricted to those that can be parsed deterministically. Parsing only; cannot be used with time2str.
See "GENERIC FORMAT PARSING" for the full grammar, rules, and examples.
Git
Default date format used by Git.
DDD MMM D HH:MM:SS YYYY ±HHMM
Parsing:
Mon Dec 1 03:04:05 2024 +0100
Mon Dec 24 15:30:45 2012 +0100
Timezone offset format: ±HHMM
Formatting:
time2str(1735052445, format => 'Git')
# 'Tue Dec 24 15:30:45 2024 +0000'
time2str(1735052445, format => 'Git', offset => 60)
# 'Tue Dec 24 16:30:45 2024 +0100'
Limitations: Fractional seconds are not supported.
ISO9075 (alias: SQL)
ISO 9075 Database Language SQL timestamp format.
YYYY-MM-DD
YYYY-MM-DD HH:MM:SS[.fraction]
YYYY-MM-DD HH:MM:SS[.fraction] ±HH:MM
Parsing:
2024-12-24
2024-12-24 15:30:45
2024-12-24 15:30:45.500
2024-12-24 15:30:45.123456789
2024-12-24 15:30:45 +01:00
2024-12-24 15:30:45.500 +01:00
Timezone offset format: ±HH:MM
Formatting:
time2str(1735052445, format => 'ISO9075')
# '2024-12-24 15:30:45 +00:00'
time2str(1735052445, format => 'ISO9075', offset => 60)
# '2024-12-24 16:30:45 +01:00'
time2str(1735052445.5, format => 'ISO9075', precision => 3, offset => 60)
# '2024-12-24 16:30:45.500 +01:00'
Limitations: Formatting always includes a timezone offset. Date-only parsing is supported but date-only output is not.
RFC2616 (aliases: RFC7231, HTTP)
HTTP-date as defined in RFC 2616 / RFC 7231. Parses three sub-formats:
DDD, DD MMM YYYY HH:MM:SS GMT # IMF-fixdate (preferred)
DDDD, DD-MMM-YY HH:MM:SS GMT # RFC 850 (obsolete)
DDD MMM _D HH:MM:SS YYYY # ANSI C asctime
Parsing:
Mon, 24 Dec 2012 15:30:45 GMT # IMF-fixdate
Monday, 24-Dec-12 15:30:45 GMT # RFC 850
Mon Dec 24 15:30:45 2012 # asctime
Formatting:
Always produces IMF-fixdate in GMT:
time2str(1735052445, format => 'RFC2616')
# 'Tue, 24 Dec 2024 15:30:45 GMT'
Limitations: Always GMT. The offset parameter is ignored.
Fractional seconds are not supported.
RFC2822 (aliases: RFC5322, IMF, EMAIL)
Internet Message Format date as defined in RFC 2822 / RFC 5322.
[DDD,] D MMM YYYY HH:MM[:SS] (±HHMM|UT|UTC|GMT|abbrev)
Parsing:
Day name and seconds are optional. Accepts numeric offsets, UTC designators (UT, UTC, GMT), and timezone abbreviations. Abbreviations are returned in tz_abbrev without resolution.
Mon, 24 Dec 2012 15:30:45 +0100
Mon, 24 Dec 2012 15:30 +0100
24 Dec 2012 15:30:45 +0100
24 Dec 2012 15:30:45 GMT
24 Dec 2012 15:30:45 CET
Timezone offset format: ±HHMM
Formatting:
Always produces a numeric offset:
time2str(1735052445, format => 'RFC2822')
# 'Tue, 24 Dec 2024 15:30:45 +0000'
time2str(1735052445, format => 'RFC2822', offset => 60)
# 'Tue, 24 Dec 2024 16:30:45 +0100'
Limitations: Fractional seconds are not supported.
RFC3339
Internet timestamp as defined in RFC 3339, a profile of ISO 8601.
YYYY-MM-DD(T|t| )HH:MM:SS[.fraction](Z|z|±HH:MM)
Parsing:
The date/time separator may be T, t, or a space. The UTC designator may be Z or z.
2024-12-24T15:30:45Z
2024-12-24t15:30:45z
2024-12-24 15:30:45Z
2024-12-24T15:30:45.500Z
2024-12-24T15:30:45.123456789Z
2024-12-24T15:30:45+01:00
2024-12-24T15:30:45-05:00
Timezone offset format: ±HH:MM
Formatting:
Always produces uppercase T and Z (or ±HH:MM):
time2str(1735052445, format => 'RFC3339')
# '2024-12-24T15:30:45Z'
time2str(1735052445, format => 'RFC3339', offset => 60)
# '2024-12-24T16:30:45+01:00'
time2str(1735052445.5, format => 'RFC3339', precision => 3)
# '2024-12-24T15:30:45.500Z'
RFC4287 (alias: ATOM)
Atom feed timestamp as defined in RFC 4287. Stricter than RFC 3339: requires uppercase T and Z, no space separator, no lowercase designators.
YYYY-MM-DDTHH:MM:SS[.fraction](Z|±HH:MM)
Parsing:
2024-12-24T15:30:45Z
2024-12-24T15:30:45.500Z
2024-12-24T15:30:45.123456789Z
2024-12-24T15:30:45+01:00
Timezone offset format: ±HH:MM
Formatting: Identical to RFC3339.
RFC5280 (alias: x509)
PKIX certificate validity times as defined in RFC 5280. Uses constrained ASN.1 UTCTime for dates before 2050 and GeneralizedTime for dates 2050 and after.
YYMMDDhhmmssZ
YYYYMMDDhhmmssZ
Parsing:
Two-digit years are expanded using the pivot year (default 1950). Four-digit years are used as-is. The Z designator is required.
121224153045Z # UTCTime (two-digit year)
491231235959Z # UTCTime, year 49 -> 2049
500101000000Z # UTCTime, year 50 -> 1950
20500101000000Z # GeneralizedTime (four-digit year)
99991231235959Z # GeneralizedTime
Formatting:
Produces UTCTime (two-digit year) for dates before 2050-01-01T00:00:00Z and GeneralizedTime (four-digit year) for dates 2050 and after:
time2str(1356359445, format => 'RFC5280')
# '121224143045Z'
time2str(2524608000, format => 'RFC5280')
# '20500101000000Z'
Limitations: Always UTC. Fractional seconds and timezone offsets are not supported; the offset parameter is ignored.
RFC5545 (alias: iCal)
iCalendar date and date-time as defined in RFC 5545.
YYYYMMDD
YYYYMMDDThhmmss[Z]
Parsing:
Date-only, date-time with and without UTC designator.
20241224 # date only
20241224T153045 # date-time, local time
20241224T153045Z # date-time, UTC
Formatting:
Always produces UTC with Z designator:
time2str(1735052445, format => 'RFC5545')
# '20241224T153045Z'
Limitations: Fractional seconds and timezone offsets are not supported. The offset parameter is ignored; formatting always produces UTC.
Ruby
Date format popularized by Ruby on Rails and Twitter.
DDD MMM DD HH:MM:SS ±HHMM YYYY
Parsing:
Mon Dec 01 03:04:05 +0100 2024
Mon Dec 24 15:30:45 +0100 2012
Timezone offset format: ±HHMM
Formatting:
time2str(1735052445, format => 'Ruby')
# 'Tue Dec 24 15:30:45 +0000 2024'
time2str(1735052445, format => 'Ruby', offset => 60)
# 'Tue Dec 24 16:30:45 +0100 2024'
Limitations: Fractional seconds are not supported.
Unix
The date(1) command output format as defined by POSIX.
DDD MMM (_D|DD) HH:MM:SS (±HHMM|UTC|GMT|abbrev) YYYY
DDD MMM (_D|DD) HH:MM:SS YYYY (±HHMM|UTC|GMT|abbrev)
Where _D is a space-padded single-digit day.
Parsing:
Accepts the timezone before or after the year. Accepts numeric offsets, UTC designators (UTC, GMT), and timezone abbreviations. Abbreviations are returned in tz_abbrev without resolution.
Mon Dec 1 03:04:05 2024 UTC
Mon Dec 24 15:30:45 2012 UTC
Mon Dec 1 03:04:05 UTC 2024
Mon Dec 24 15:30:45 UTC 2012
Timezone offset format: ±HHMM
Formatting:
Always produces the zone-before-year. Uses UTC for zero offset and a numeric offset otherwise.
time2str(1735052445, format => 'Unix')
# 'Tue Dec 24 15:30:45 UTC 2024'
time2str(1735052445, format => 'Unix', offset => 60)
# 'Tue Dec 24 16:30:45 +0100 2024'
Limitations: Fractional seconds are not supported.
W3CDTF (alias: W3C)
W3C Date and Time Format, a profile of ISO 8601.
YYYY
YYYY-MM
YYYY-MM-DD
YYYY-MM-DDTHH:MM:SS[.fraction](Z|±HH:MM)
Parsing:
Supports partial dates. A timezone designator is required when a time component is present.
2024 # year only
2024-12 # year and month
2024-12-24 # date only
2024-12-24T15:30:45Z # full datetime
2024-12-24T15:30:45.500Z
2024-12-24T15:30:45.123456789Z
2024-12-24T15:30:45+01:00
Timezone offset format: ±HH:MM
Formatting: Identical to RFC3339.
GENERIC FORMAT PARSING
The generic format parser accepts a wide variety of real-world date/time representations, restricted to those that can be parsed deterministically. A date is always required. Time and timezone are optional, but a timezone may only appear when a time is present.
Date
A date is always required. Three categories are accepted. Day names, month names, Roman numerals, and ordinal suffixes are all case-insensitive.
Numeric Dates (Y-M-D only)
When all three components are numeric, they must appear in year-month-day order to avoid the ambiguity between American (M/D/Y) and European (D/M/Y) conventions. The separator must be a hyphen, slash, or period, consistent within the date.
2024-12-24
2024/12/24
2024.12.24
These are rejected:
12-24-2024 # M-D-Y not accepted
24-12-2024 # D-M-Y not accepted
2024-12/24 # mixed separators
Dates with Textual Months
When the month is given as a name or Roman numeral it is unambiguous, so the day and year may appear in any order relative to the month. Month names may be abbreviated (Jan, Feb, ...) or written in full (January, February, ...).
Roman numerals (I through XII) are accepted only in day-month-year order.
Separator-based (hyphen, slash, or period, consistent within the date):
2024-Dec-24 # Y-M-D
24-Dec-2024 # D-M-Y
Dec-24-2024 # M-D-Y
2024/December/24
24.XII.2024 # Roman numeral, D-M-Y only
Space-separated:
24 December 2024
December 24, 2024
24. XII. 2024
In space-separated dates, an ordinal suffix (st, nd, rd, th) or a trailing period may follow the day. A trailing period or comma may follow the month:
24th December 2024
24. December 2024
December 24th, 2024
24. XII. 2024
24 XII. 2024
24. XII 2024
Compact Dates (No Separators)
Accepted only when the month is textual. Roman numerals are accepted in day-month-year order:
24DEC2024
24Dec2024
2024DEC24
2024Dec24
24XII2024
Day Names
An optional day name prefix (e.g., Monday, or Mon,) is accepted before the date but not validated against the actual date.
Monday, 24 December 2024
Mon, 24 Dec 2024
Year
A four-digit year is always required. Two-digit years are not accepted.
Time of Day
Optional. When present, it must be separated from the date by T, a comma and space, the word at surrounded by spaces, or a plain space.
2024-12-24T15:30:45
2024-12-24 15:30:45
December 24, 2024, 15:30
Monday, 24th December 2024 at 3:30 pm
Either HH:MM or HH with an AM/PM indicator is required as a minimum.
24-Hour Time
Hours and minutes separated by a colon. Hours may be one or two digits; minutes are always two digits. Seconds are optional (two digits, colon-separated). An optional fractional part may follow the seconds, separated by a period or comma, up to nine digits.
15:30
9:05
15:30:45
15:30:45.500
15:30:45,500
15:30:45.123456789
12-Hour Time
An AM/PM indicator is required. Hours must be 1-12. Minutes, seconds, and fractional seconds follow the same rules as 24-hour time but are optional. The indicator may appear with or without a separating space.
Accepted forms: AM, am, PM, pm, A.M., a.m., P.M., p.m.
3 PM
3PM
3:30 PM
3:30:45 pm
3:30:45.500 P.M.
12 p.m.
Midnight is 12:00 AM, noon is 12:00 PM.
Timezone
Optional; may only appear when a time is present.
UTC Designators
Z, UTC, and GMT set tz_utc to the matched designator and tz_offset to 0, unless followed by a numeric offset (e.g., UTC+05:30), in which case tz_offset reflects that offset.
Numeric Offsets
±1
±01
±0100
±01:00
±05:30
Combined UTC and Offset
UTC or GMT followed immediately by a numeric offset. tz_utc is set to the designator; tz_offset reflects the numeric part:
UTC+1
UTC+01:00
GMT+5:30
Timezone Abbreviations
Abbreviations matching [A-Z][A-Za-z][A-Z]{1,4} are accepted. UTC designators are handled as above; all others (e.g., EST, CET, IST) are returned in tz_abbrev without resolution.
Timezone Annotations
RFC 9557 (IXDTF) bracketed tags and Java ZoneId annotations are captured in tz_annotation. Parenthesized comments are accepted but discarded.
+01:00[Europe/Stockholm]
+01:00[u-ca=hebrew]
+0100[Europe/Stockholm]
+0100 (CET)
+0100 (Central European Time)
Validation
Dates must be valid for the Gregorian calendar, including leap years
Hours: 0-23 (24-hour) or 1-12 (12-hour with AM/PM)
Minutes: 0-59
Seconds: 0-60 (60 allows for leap seconds)
Examples
# ISO 8601
2024-12-24
2024-12-24T15:30
2024-12-24T15:30+01
2024-12-24T15:30:45,500+01
# RFC 3339
2024-12-24T15:30:45+01:00
2024-12-24T15:30:45.500+01:00
# RFC 9557
2024-12-24T15:30:45.500+01:00[Europe/Stockholm]
# RFC 2822
Mon, 24 Dec 2024 15:30:45 +0100
24 Dec 2024 15:30 +0100
# RFC 2616 (HTTP)
Mon, 24 Dec 2024 15:30:45 GMT
# RFC 9051 (IMAP)
24-Dec-2024 15:30:45 +0100
# ISO 9075 (SQL)
2024-12-24 15:30:45
2024-12-24 15:30:45.500 +01:00
# ECMAScript Date.prototype.toString
Mon Dec 24 2024 15:30:45 GMT+0100 (Central European Time)
# Long-form textual
Monday, 24 December 2024, 15:30 GMT+1
Monday, 24th December 2024 at 3:30 pm UTC+1
December 24th, 2024 at 3:30 PM
# Short-form variations
Dec/24/2024 03:30:45 PM
24. XII. 2024 12PM UTC+1
24DEC2024 12:30:45.500
24.Dec.2024 15:30:45
TIMEZONE ABBREVIATIONS
The Generic, RFC2822, and Unix parsers accept timezone abbreviations.
UTC designators (
UTC,GMT,UT,Z)Unambiguous. Set
tz_utcto the matched designator andtz_offsetto 0, unless followed by a numeric offset.All other abbreviations
Returned as-is in
tz_abbrev.tz_offsetwill not be present. This module intentionally does not resolve abbreviations likeEST,CET, orISTto numeric offsets, as many are ambiguous (e.g.,ISTcould mean India Standard Time UTC+5:30, Israel Standard Time UTC+2, or Irish Standard Time UTC+1).
str2time requires a resolved offset and will croak if only an unresolved abbreviation is present. Use str2date to retrieve the components including tz_abbrev, then resolve externally:
my %d = str2date('24 Dec 2012 15:30:45 IST', format => 'RFC2822');
# (..., tz_abbrev => 'IST')
SEE ALSO
Time::Moment, DateTime, Time::Piece
STANDARDS
ISO 8601:2004 - Data elements and interchange formats
RFC 3339 - Date and Time on the Internet: Timestamps
RFC 2822 / RFC 5322 - Internet Message Format
RFC 2616 / RFC 7231 - HTTP/1.1
RFC 4287 - The Atom Syndication Format
RFC 5280 - Internet X.509 Public Key Infrastructure (PKIX)
RFC 5545 - Internet Calendaring and Scheduling (iCalendar)
RFC 9051 - Internet Message Access Protocol (IMAP)
RFC 9557 - Date and Time on the Internet: Timestamps with Additional Information
ISO 9075 - SQL Database Language
ITU-T X.680 (ISO/IEC 8824-1) - ASN.1
W3C Date and Time Formats
AUTHOR
Christian Hansen
COPYRIGHT AND LICENSE
Copyright (C) 2026 by Christian Hansen
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.