chansen/p5-time-str
Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
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 within
"RFC2616"), 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: 49 becomes 2049, 50 becomes 1950, 99
becomes 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_offset" reflects that offset rather than zero.
* "tz_abbrev" - The timezone abbreviation as it appeared in the input,
if present and not a UTC designator. "tz_offset" will not be present
when "tz_abbrev" is set. See "TIMEZONE ABBREVIATIONS".
* "tz_annotation" - Bracketed timezone tag from the input, if present
(RFC 9557 IXDTF or Java "ZoneId" format, e.g.,
"[Europe/Stockholm]"). Informational only; does not affect
"tz_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 .999 at 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 $time and bypasses rounding. Use
this for exact control over fractional output or to preserve
nanosecond precision that floating-point cannot represent. Can be
combined with "precision" to control zero-padding.
Returns
A formatted date/time string.
Errors
Croaks if:
* $time is outside the supported range
* A 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 "nanosecond" parameter 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"
See "TIMEZONE ABBREVIATIONS".
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"
See "TIMEZONE ABBREVIATIONS".
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.
See "TIMEZONE ABBREVIATIONS".
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_utc" to the matched designator and "tz_offset"
to 0, unless followed by a numeric offset.
* All other abbreviations
Returned as-is in "tz_abbrev". "tz_offset" will not be present. This
module intentionally does not resolve abbreviations like "EST",
"CET", or "IST" to numeric offsets, as many are ambiguous (e.g.,
"IST" could 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.