Date::Manip::Date(3)
โจ NAME โจ
Date::Manip::Date โ bestie, this is THE module for working with date objects ๐ it's from the Date::Manip::Date(3) page in the User Contributed Perl Documentation, and honestly? she ate.
๐ธ SYNOPSIS ๐ธ
use Date::Manip::Date;
$date = new Date::Manip::Date;
๐ฆ DESCRIPTION ๐ฆ
okay so, real talk: this module works specifically with date objects. that's her whole thing. her niche. her main character era. ๐
ngl though, the word "date" is lowkey misleading here โ not in a shady way, just like, it's doing more than you think. Date::Manip works with the full calendar date (year, month, day, and week when appropriate), the time of day (hour, minute, second), and the time zone. it's giving very thorough. very detail-oriented.
what it does not do: fractional seconds. nope. not invited to the party. ๐ซ
๐ METHODS ๐
base config err is_date is_delta is_recur new new_config new_date new_delta new_recur tz
so for all of these ones up here ๐ bestie you gotta go read the Date::Manip::Obj documentation. they live over there. not here. i don't make the rules. ๐ซถ
calc
$date2 = $date->calc($delta [,$subtract]);
$delta = $date->calc($date2 [,$subtract] [,$mode]);
please refer to the Date::Manip::Calc documentation for the details on this one, bestie. it's a whole thing and it has its own page. โจ
cmp
$val = $date1->cmp($date2);
this compares two different dates โ and yes, both of them must be valid date objects, no shortcuts, no fakes, we don't do that here. ๐
it returns -1, 0, or 1, just like the cmp or <=> operators in perl. iconic behavior, honestly.
the comparison will automatically handle time zone differences between the two dates (i.e. they will be sorted in order as they appear in the GMT zone). so no matter where in the world these lil dates are from, they get sorted fairly. ๐
โ ๏ธ a warning gets printed if either of the date objects does not include a valid date. so likeโฆ watch out.
complete
$flag = $date->complete([$field]);
this tests the date stored in the object to see if it is complete or truncated (there's a whole discussion of this below, keep reading bestie).
if no $field is passed in, it returns 1 if the date is complete, or 0 if it was truncated and default values have been supplied. simple as that. โจ
if $field is passed in, it may be one of: m, d, h, mn, s . it will return 1 if the value for that field was specified, or 0 if a default was used.
convert
$err = $date->convert([$zone]);
this converts the date stored in the object to a different time zone. ๐
$zone can be the name of a time zone. if it is not passed in, the date is converted to the local time zone. easy peasy.
holiday
$name = $date->holiday();
@name = $date->holiday();
$name = $date->event();
this returns the name of the holiday if $date is a holiday. if $date is not a holiday, undef is returned. and if $date is an unnamed holiday, an empty string is returned. (she's mysterious like that. ๐)
in scalar context, holiday returns the name of one holiday that occurs on that date (the one first defined in the config file). in list context, it returns all holidays on that date. slay.
input
$str = $date->input();
this returns the string that was parsed to form the date. like, the receipts. the origin story. ๐
is_business_day
$flag = $date->is_business_day($checktime);
this returns 1 if $date is a business day. ๐ผ
$checktime may be passed in. if it is non-zero, the time is checked to see if the date is a business day and falls within work hours. clocking in, bestie. โฐ
list_holidays
@date = $date->list_holidays([$y]);
this returns a list of Date::Manip::Date objects containing all dates during a year which are holidays. the times will all be 00:00:00. midnight energy. ๐
if $y is not passed in, it will list the holidays in the same year as the date stored in $date (if any) or in the current year otherwise.
list_events
@list = $date->list_events( [$format] );
@list = $date->list_events(0 [,$format]);
@list = $date->list_events($date1 [,$format]);
this returns a list of events. events are defined in the Events section of the config file (discussed in the Date::Manip::Holidays manual). ๐
in the first form, a list of all events active at the precise time stored in $date will be returned.
if the first argument evaluates to 0, a list of all events active at any time during that day (Y,M,D) are returned.
if the first argument is another date object, all events that are active at any time between the two dates (inclusive) are returned.
by default, the list returned is of the form:
( [START, END, NAME],
[START, END, NAME],
...
)
where START is a date object when an event starts, END is a date object when it ends, and NAME is the name of the event. note that START and END are the actual start and end date of the event and may be outside the range of dates being examined (though the event will obviously overlap the range or it wouldn't be included in the list). so like, she's giving you the full picture, not just the cropped version. ๐ธ
if $format is included, it can specify an alternate format for the output. currently, the only supported format is named dates and it returns a list in the form:
( [DATE1, NAME1a, NAME1b, ...],
[DATE2, NAME2a, NAME2b, ...],
...
)
this includes a list of all dates during the range when there is a change in what events are active. DATE1 will always be the start of the range being considered, and (NAME1a, NAME1b, ...) are the list of all events that will be active at that time. at DATE2, the list of active events changes with (NAME2a, NAME2b, ...) being active.
it is quite possible that a date be included which has no active events, and in that case, the list of names will be empty. ๐ (empty list era, it happens)
nearest_business_day
$date->nearest_business_day([$tomorrowfirst]);
this looks for the work day nearest to $date. if $date is a work day, it is left unmodified โ she's already perfect, no edits needed. ๐
otherwise, it will look forward or backwards in time 1 day at a time until a work day is found. if $tomorrowfirst is non-zero (or if it is omitted and the config variable TomorrowFirst is non-zero), we look to the future first. otherwise, we look in the past first.
in other words, in a normal week:
- if
$dateis Wednesday,$dateis returned. - if
$dateis Saturday, Friday is returned. - if
$dateis Sunday, Monday is returned. - if Wednesday is a holiday, Thursday is returned if
$tomorrowfirstis non-nil or Tuesday otherwise.
periodt. ๐๏ธ
next_business_day
prev_business_day
$date->next_business_day($off [,$checktime]);
$date->prev_business_day($off [,$checktime]);
the next_business_day method sets the given date to $off (which can be a positive integer or zero) business days in the future. the prev_business_day method sets the date to $off business days in the past.
first, $date is tested. if $checktime is nonzero, the date must fall on a business date, and during business hours. if $checktime is zero, the time check is not done, and the date must simply fall on a business date.
if the check fails, the date is moved to the start of the next business day (if $checktime is nonzero) or the next business day at the current time (if $checktime is zero). otherwise, it is left unmodified.
next, if $off is greater than 0, the day $off work days from now is determined.
๐จ one thing to note for theprev_business_daymethod is that if$datecheck fails, the date is set to the next business date, exactly likenext_business_day. in other words, if$dateis not a business day, the call:
$date->prev_business_day(0 [,$checktime]);
moves $date forward in time instead of backward which is nonintuitive, but you just have to think of day 0 as being the next business day if $date is not a business day. i know. i know. ๐ญ it's giving chaos but it's documented chaos so we vibe.
as a result, the following two calls ALWAYS give the same result:
$date->next_business_day(0 [,$checktime]);
$date->prev_business_day(0 [,$checktime]);
no matter what date is stored in $date. no cap. ๐ฅ
parse
$err = $date->parse($string [,@opts]);
this parses a string which should include a valid date and stores it in the object. if the string does not include a valid date, an error is returned. use the err method to see the full error message. ๐
a full date may include a calendar date (year, month, day), a time of day (hour, minute, second), and time zone information. all of this can be entered in many different formats. she's flexible like that. ๐ง
for information on valid date formats, refer to the section VALID DATE FORMATS. for information on valid time zone information, refer to the section VALID TIME ZONE FORMATS.
if no time zone information is included in the date, it is treated as being in the local time zone.
if time zone information is included, the date will be kept in that time zone, and all operations will be done in that time zone. the convert method can be used to change the time zone to the local time zone, or to another time zone. ๐
some things to note:
- all strings are case insensitive.
"December"and"DEceMBer"are equivalent. (she does not care about your caps lock era. ๐ ) - when a part of the date is not given, defaults are used. this is described below in the section "Complete vs. truncated dates and times".
- the year may be entered as 2 or 4 digits. if entered as 2 digits, it will be converted to a 4 digit year. there are several ways to do this based on the value of the
YYtoYYYYconfig variable. refer to theDate::Manip::Configdocumentation for more details. - dates are always checked to make sure they are valid. no invalid dates sneaking through. ๐ซ
- if any other arguments are passed in, they act as options which may improve the speed of parsing. these include:
noiso8601โ do not try to parse the date as an ISO 8601 date or time.nodowโ do not try to parse a day-of-week (Monday) in the string.nocommonโ do not try to parse the date using the formats in the "Common date formats" section.nootherโ do not try to parse the date using the "Less common date formats" or a time using the "Other time formats".nospecialโ do not try to parse the date using the "Special date strings" formats or a time using the "Special time strings" formats, or as a combined date/time using the "Additional combined date and time" formats.nodeltaโ do not treat deltas as a date relative to now.noholidaysโ do not parse holiday names as dates.
parse_date
$err = $date->parse_date($string [,@opts]);
โฆto be continued bestie, there's more page coming ๐
Okay so this one takes a string that's got a whole entire valid date hiding inside it and sets the date part of the object. ๐ No time stuff, just date.
If the object already had a valid date in it? The time is kept unchanged โ not a single second touched. But if the object did NOT have a valid date, you get a time of 00:00:00. Fresh start, blank slate, main character energy. โจ
@opts can be any of the strings described in the parse method above. ๐
parse_time โฐ
$err = $date->parse_time($string [,@opts]);
This one parses a string and sets the time portion of $date to whatever it finds in there. ๐
If the object had a valid date already, the Y/M/D portion is left alone, untouched, no notes. Otherwise? The current date gets used as the base. ๐ซถ
@opts can be 'noiso8601' or 'noother'. That's it, that's the whole list.
parse_format ๐
$err = $date->parse_format($format,$string);
($err,%match) = $date->parse_format($format,$string);
This parses a date living inside $string based on the explicit format info you hand it in $format. It's giving very much "I will tell you exactly what to look for." ๐
- If the format is invalid,
$errwill hold an error message. - If the format is valid but the string doesn't match? You get an error code of
1back.
If you call it in array context, a hash gets returned containing %+. That's mainly useful when your $format string has some named capture groups that you defined. We get into that below, bestie. โฌ๏ธ
So like โ $format is a string containing a regular expression, except with some special directives sprinkled in (based on the printf directives). Those directives get turned into regular expression components, and then the whole string becomes a regular expression which, if $string matches it, will return the date. โจ
The directives available are identical to the printf directives. So if your $format string has '%Y' in it, it'll match a 4-digit year. Easy.
All of the printf directives are available here, with a few caveats:
%lโ this directive is NOT available. It said what it said. ๐%b,%h,%Bโ all of these will match a month name or abbreviation.%v,%a,%Aโ all of these will match a day name or abbreviation.%z,%Z,%Nโ these will match any time zone string.%nโ multi-line matching is not currently supported, so this directive is not allowed.%xโ all format directives are converted to a regular expression and then cached (so that a format can be reused without the penalty of doing the conversion to a regular expression with each use). As a result, if you need to set theDateFormatconfig variable (which determines the meaning of the%xdirective), it must be done before a format string containing%xis used. If theDateFormatconfig variable is set afterwards, the format string will reflect the old, NOT THE NEW, value ofDateFormat. Read that again. ๐จ
Your format string may not over-specify the date. In other words, you may not include both a%yand%Ydirective, or both a%jand%mdirective. Pick a lane. ๐
A valid format string will specify any of the following sets of data:
Required Optional
M D H Mn S Y Zone Day-of-week
M D H Mn Y Zone Day-of-week
M D Y Zone Day-of-week
H Mn S Zone
H Mn Zone
For example, if you had a date stored as:
YYYY.MM-DD
you could match it using the following:
$date->parse_format('%Y\\.%m\\-%d',$string);
And if you wanted to extract the date out of an apache log line:
10.11.12.13 - - [17/Aug/2009:12:33:30 -0400] "GET /favicon.ico ...
you could use:
$date->parse_format('.*?\\[%d/%b/%Y:%T %z\\].*',$line);
When you're matching months, days, and hours, there are two directives that could be used (for the numerical versions, anyway). For the month, you may use %m or %f. If your date is known to have a two-digit month, you should use %m. If it contains a one- or two-digit month, you must use %f (and it is safe to use %f for two-digit months). Similarly, for days you can use %d or %e, and for hours you can use %H or %k. In both cases, the first can only be used if you are guaranteed a 2-digit value. ๐
In your format string you may use capture groups (or back references to them) in the regular expression using all of the rules of normal regular expressions. Since Date::Manip uses named capture groups internally, it is suggested that you also use named groups. Mixing numbered and named groups will work... but it'll be entirely up to you to keep track of what numbers refer to which capture groups. Good luck with that. ๐ซ
Every printf directive adds one or more named capture groups to the regular expression. If you use named groups in the format string, they must not conflict with the ones used internally, or else the date will probably not be parsed correctly.
The following named capture groups are used internally:
y
m
d
h
mn
s
mon_name
mon_abb
dow_name
dow_abb
dow_char
dow_num
doy
nth
ampm
epochs
epocho
tzstring
off
abb
zone
g
w
l
u
To be safe, it is suggested that any additional named capture groups introduced by the programmer start with a capital letter. This is guaranteed to never conflict with any existing, or future, named capture groups. Iconic safety hack, honestly. ๐ก๏ธ
In order to get access to the values stored in those additional named capture groups, the parse_format function must be called in list context, and the %+ array will be returned as the second value.
As an example:
$string = "before 2014-01-25 after";
($err,%m) = $date->parse_format('(?<PRE>.*?)%Y-%m-%d(?<POST>.*)',$string);
would return a hash (%m) with the following key/value pairs:
'PRE' => 'before '
'POST' => ' after'
prev / next ๐
The prev method changes the date to the previous (or current) occurrence of either a day of the week, a certain time of day, or both. The next method changes the date to the next (or current) occurrence. The examples below illustrate the prev method, but the next one is identical in operation. Same energy, opposite direction. ๐
There are two different ways to use this method. The first is to pass in a day of week and possibly a time:
$err = $date->prev($dow, $curr [,$time]);
- If
$curr = 0, this means to look for the previous occurrence of the day of week, and set the time to the value passed in (or current time if no time was passed in). The day is ALWAYS less than the current day. If the current day is the same day of week as$dow, then the date returned will be one week earlier. - If
$curr = 1, it means to look for the current or previous occurrence of the day of week, and set the time to the value passed in (or00:00:00if none was passed in). If the current day of week is the same as$dow, the date will remain unchanged. Since the time is then set, the new date may actually occur after the original date depending on the value of$time. Yeah, that's a plot twist, but it's in the docs. ๐ - If
$curr = 2, it means to look for the last time (not counting now) that the day of week at the given time occurred. The date may be the same as the original date.
$time may be a list reference of [H,MN,S], [H,MN], or [H].
The following examples should illustrate the use of this function.
Original Date = Fri Nov 22 18:15:00
dow curr time new date
4 (Thu) 0/1/2 undef Thu Nov 21 00:00:00
4 0/1/2 [12,30,0] Thu Nov 21 12:30:00
5 (Fri) 0/2 undef Fri Nov 15 18:15:00
5 1 undef Fri Nov 22 18:15:00
5 0 [12,30,0] Fri Nov 15 12:30:00
5 1/2 [12,30,0] Fri Nov 22 12:30:00
5 0/2 [19,30,0] Fri Nov 15 19:30:00
5 1 [19,30,0] Fri Nov 22 19:30:00
The second way to use this method is by passing in undef for the day of week.
$err = $date->prev(undef,$curr,$time);
In this case, a time is required and it must be a list reference of 3 elements: [H, MN, S]. Any or all of the elements may be undef.
The new date is the previous occurrence of the time.
- If you define hours, then minutes and seconds may be defined, or default to
0, and you are looking for a previous time that the specified time (HH:00:00) occurred (which might be as much as 24 hours in the past). - If hours are undefined and minutes are defined, then seconds may be defined, or default to
0, and you are looking for the last time the minutes/seconds (MN:SS) appeared on the digital clock, which will be sometime in the past hour. - Finally, if hours and minutes are undefined, seconds must be defined (or default to zero) and the last time that that second occurred will be returned (which will be sometime in the past minute).
If $curr is non-zero, the current time is returned if it matches the criteria passed in, so the returned value will be now or in the past. If $curr is zero, the time returned will definitely be in the past. No take-backs. โณ
DATE = Fri Nov 22 18:15:00
curr hr min sec returns
0/1 18 undef undef Nov 22 18:00:00
0/1 18 30 0 Nov 21 18:30:00
0 18 15 undef Nov 21 18:15:00
1 18 15 undef Nov 22 18:15:00
0 undef 15 undef Nov 22 17:15:00
1 undef 15 undef Nov 22 18:15:00
printf ๐จ๏ธ
$out = $date->printf($in);
@out = $date->printf(@in);
This takes a string, or a whole list of strings, which may contain any number of special formatting directives. Those directives get replaced with information contained in the date. Everything else in the string is returned unmodified. ๐
A directive always begins with '%'. They are described below in the section PRINTF DIRECTIVES. Go look, bestie. ๐
secs_since_1970_GMT ๐ฐ๏ธ
$secs = $date->secs_since_1970_GMT();
This returns the number of seconds that have elapsed since Jan 1, 1970 00:00:00 GMT (negative if the date is earlier). Classic Unix epoch moment. ๐งฎ
The reverse is also allowed:
$err = $date->secs_since_1970_GMT($secs);
which sets the date to $secs seconds from Jan 1, 1970 00:00:00 GMT in the local time zone. Note that little detail, it matters. ๐
set ๐ ๏ธ
$err = $date->set($field,@vals [,$isdst]);
okay so this method is literally the glow-up button for a date โ it explicitly sets one or more fields on it, no cap ๐
$field can be any of these besties:
$field @vals
zone [ZONE] ZONE can be any zone or alias
zdate [ZONE,]DATE sets the zone and entire date
date DATE sets the entire date
time TIME sets the entire time
y YEAR sets one field
m MONTH
d DAY
h HOUR
mn MINUTE
s SECOND
So here's the tea: DATE is a list reference holding [Y,M,D,H,MN,S] and TIME is a list reference holding [H,MN,S] โจ
ZONE is optional and lowkey defaults to the local zone โ which is either whatever the system clock says, or whatever you set with the SetDate or ForceDate config variables. If you do pass it in, it can be any zone name, abbreviation, or offset. An offset can be a valid offset string, or a list reference. Wanna know what counts as a valid offset string? Go peek at the join/split functions of Date::Manip::Base ๐ซถ
There's an optional last argument, $isdst, and it has to be 0 or 1. You only include it when you're setting a date that could land in either standard time or daylight saving time. In every other situation it just gets ignored, periodt. And if you don't include it, but the resulting date could be in either one? It defaults to standard time. that's the default, bestie, remember it
The $date object has to already contain a valid date โ unless you're setting the entire date with $field as "zdate" or "date" ๐
- If
$fieldis"zone", the time zone of the date gets set. IfZONEisn't passed in, it becomes the local time zone. But heads up: when you set the time zone, no conversion is done! Whatever date and time was stored in the$dateobject before stays exactly the same... it's just now that same date and time in the new time zone. it's giving "same girl, new city" ๐ญ - If
$fieldis"zdate", the entire date and the time zone get set. IfZONEisn't passed in, it defaults to the local time zone. - If
$fieldis"date", the entire date gets set, but the time zone of the date does not change. - If
$fieldis"time", or one of the individual fields (y,m,d,h,mn,s), then only those fields get modified.
An error comes back if you pass in an invalid argument list, or if the resulting date gets checked and turns out to be invalid ๐
โจ value โจ
$val = $date->value([$type]);
@val = $date->value([$type]);
These hand you back the value of the date that's stored in the object, bestie ๐
In scalar context you get a printable string shaped like YYYYMMDDHH:MN:SS. In list context you get a list of (Y,M,D,H,MN,S).
If $type is omitted, the date comes back in the time zone it was parsed in.
If $type is "local", it comes back in the local time zone โ which is either the system time zone, or the zone you specified with the SetDate or ForceDate config variables.
If $type is "gmt", the date comes back in the GMT time zone ๐
An empty string or an empty list comes back in the case of an error (and an error code gets set, so check for it ๐).
โจ week_of_year โจ
$wkno = $date->week_of_year([$first]);
This one figures out the week number for the date stored in $date. It uses the config variables FirstDay and Week1ofYear to work it out. For historical reasons, an argument $first may be passed in. It has to be between 1 and 7, and it refers to the first day of the week, overriding whatever the FirstDay variable is set to.
NOTE: This routine should only be called in rare cases. Useprintfwith the%W,%U,%J,%Lformats instead, because that will always return the correct values for week and year. no cap, just useprintf๐ญ
This routine returns a week between 0 and 53, which you then have to "fix" to get into the ISO 8601 weeks from 1 to 53. A date that returns a week of 0 actually belongs to the last week of the previous year. A date that returns a week of 53 may belong to the first week of the next year. so yeah, "fix" is doing a lot of heavy lifting there ๐
๐ ISSUES WITH PARSING DATES ๐
These are the situations that can pop up when parsing dates โ get familiar with them so you can make full use of this module, bestie ๐ฆ
Complete vs. truncated dates and times
Date formats are either complete or truncated. A complete date fully specifies the year, month, and day, and a complete time fully specifies the hour, minute, and second.
You gotta understand that in so many instances the info might be implied rather than explicitly stated โ but it's still treated as complete. fr fr.
For example, the date "January 3" is complete because it implies the current year.
A truncated calendar date or time doesn't include info about some of the fields. Date::Manip will never work with a partial date or time, so defaults get supplied instead.
For example, the date "2009-01" is missing a day field, so a default gets used. In this case the day becomes the 1st, so it's equivalent to "Jan 1st 2009". If only the year is given, it defaults to Jan 1.
If the time, or any of its components, is missing, they default to 00. So the time "12:30" and "12:30:00" are equivalent โจ
The "complete" method can be used to check what type of date was parsed, and which values were specified (either explicitly or implied) and which were provided as a default. Heads up tho: there's no way to differentiate between an explicit value and an implied one.
A string with a date and/or time may consist of any of the following:
a complete date and a time (complete or truncated)
a truncated date with no time
a time (complete or truncated) with no date
In other words, the date "Jan 2009 12:30" is not valid โ because it's a time hanging out with a truncated date. that combo is just not it ๐ญ
๐ VALID TIME ZONE FORMATS ๐
When you're specifying a time zone, there are three different ways to do it, bestie:
- Specify the actual time zone.
- Supply a valid time zone abbreviation.
- Specify an offset (with an optional abbreviation).
The following dates illustrate these formats.
The timezone info always follows the time immediately, and may only be included if a time is included. The examples below use an ISO 8601 format for the date/time, but literally any of the other date and time formats may be used ๐
The first way to specify the time zone is to specify it by complete name (or by using one of the standard aliases):
2001-07-01-00:00:00 America/New_York
Even though this is unambiguous when it comes to determining the time zone, the time itself is ambiguous in most zones for one hour of the year. When a time change happens and the clock gets moved back, the same wall clock time occurs twice. it's giving "which one is the real one" ๐
For example, in America/New_York, on Sunday, Nov 2, 2008, at 02:00 in the morning, the clock was set back to 01:00. As a result, the date Nov 2, 2008 at 01:30 is ambiguous. There's literally no way to determine if this refers to the 01:30 that happened half an hour before the time change, or the one 30 minutes after the change.
In practice, if this form is used, the date gets assigned to standard time, meaning there will be some times (typically 1 hour per year) that just cannot be expressed this way. As such, this method is discouraged. periodt.
The second way to specify the time zone โ and this is the most common one โ is to use a time zone abbreviation:
2001-07-01-00:00:00 EDT
Unfortunately, the abbreviation doesn't uniquely determine the time zone except in a few cases ๐ญ In order to assign a time zone, Date::Manip will refer to a list of all time zones which use the abbreviation. They get tested in the order given in the Date::Manip::Zones documentation, and the first match โ meaning the one where the given date/time and abbreviation are valid โ determines the time zone that gets used. A great deal of effort has been made to make sure the most likely time zone gets obtained (i.e. the most common time zones are tested before less common ones), so in most cases you'll get the results you wanted ๐
If the default order doesn't give you the time zone you're after, the order of testing can be modified using the abbrev method described in the Date::Manip::TZ documentation.
So the time zone is ambiguous, but the date isn't โ because only time zones for which the date is valid will get used โจ
The third way to specify the time zone is by specifying an offset and an optional abbreviation:
2001-07-01-00:00:00 -04
2001-07-01-00:00:00 -0400
2001-07-01-00:00:00 -040000
2001-07-01-00:00:00 -04:00
2001-07-01-00:00:00 -04:00:00
2001-07-01-00:00:00 -04 (EDT)
2001-07-01-00:00:00 -0400 (EDT)
2001-07-01-00:00:00 -040000 (EDT)
2001-07-01-00:00:00 -04:00 (EDT)
2001-07-01-00:00:00 -04:00:00 (EDT)
2001-07-01-00:00:00 -04 EDT
2001-07-01-00:00:00 -0400 EDT
2001-07-01-00:00:00 -040000 EDT
2001-07-01-00:00:00 -04:00 EDT
2001-07-01-00:00:00 -04:00:00 EDT
Just like with the abbreviation, the offset is almost never enough to uniquely determine the time zone (and it's not even guaranteed that both the offset and the abbreviation will be, though in practice it's probably sufficient). In this instance, the time zone gets determined by testing all time zones which have the given offset (and abbreviation, if it's included) until one is found which matches the pieces of information supplied. For more info on how this testing is done, go read the def_zone method in the Date::Manip::TZ documentation ๐ซถ
๐ VALID DATE FORMATS ๐
There are several categories of date formats that Date::Manip supports. These are strings which specify only the year/month/day fields, bestie.
These formats explicitly set the date, but not the time. They can be combined with a time string (as specified below) to set both the date and the time. If you don't do that, the default time is determined by the DefaultTime config variable.
ISO 8601 dates
The preferred date formats are the ones specified by ISO 8601. The specification includes valid calendar date and valid time formats. Date::Manip will handle all of these formats, but doesn't require that the dates rigidly adhere to the spec โ because the ultimate goal of Date::Manip is to handle dates as they're represented in real life, and some common variations exist which are similar to, but not identical to, the ones from the specification. it's giving "we're flexible, we get it" ๐
A calendar date includes the following fields:
CCโ the 2-digit century, bestie ๐YYโ the 2-digit year inside a centuryMMโ 2-digit monthDDโ 2-digit day of the monthDoYโ 3-digit day of the year (001-366)Wwwโ the literal characterWfollowed by a 2-digit week of the year (01-53)Dโ the day of the week (1-7)
The date formats that are, like, fully complete โจ
Date::Manip counts the following date formats as complete. For all of these examples we're using the date Thu Mar 5 2009 โ that's the 64th day of the year, Thu is the 4th day of the week, and the week starting Mon, Mar 2 is the 10th week of the year (per the ISO 8601 definition, obviously ๐).
And like, obvi some of these formats only work at certain times?? For example --MMDD means a month and day in the current year, so the date Mar 5, 2009 can only be written this way during 2009. Girl, time is a construct. ๐ฆ
Format Notes Examples
CCYYMMDD 20090305
CCYY-MM-DD 2009-03-05
YYMMDD 1,2,4 090305
YY-MM-DD 09-03-05
-YYMMDD 3,4 -090305
-YY-MM-DD -09-03-05
--MMDD 1 --0305
--MM-DD --03-05
---DD 1 ---05
CCYYDoY 2009064
CCYY-DoY 2009-064
YYDoY 1,4 09064
YY-DoY 09-064
-YYDoY 3,4 -09064
-YY-DoY -09-064
-DoY 1 -064
CCYYWwwD 2009W104
CCYY-Www-D 2009-W10-4
YYWwwD 1,4 09W104
YY-Www-D 09-W10-4
-YYWwwD 3,4 -09W104
-YY-Www-D -09-W10-4
-YWwwD 1 -9W104
-Y-Www-D -9-W10-4
Y is the year (0-9) in
current decade
-WwwD 1 -W104
-Www-D -W10-4
-W-D 1 -W-4
D is day (1-7) in
current week
---D 1 ---4
same as -W-D
Notes, because there are always notes ๐
- These formats are considered truncated in the standard, but since they do include (or imply, using the current date for defaults) all of the fields, and since they don't introduce any parsing complexities, the standard is relaxed and they're treated as complete. Iconic of them honestly. ๐
- These formats are treated differently than in Date::Manip 5.xx, as described below. Yeah. We'll get there. ๐
- These formats are not defined in the ISO 8601 spec, but they're added for the sake of completeness since they don't add any parsing incompatibilities. Filling in the gaps, main character energy. ๐
- Formats where the century isn't given are described as a year in the current century in the specification. Date::Manip treats this more generically using the
YYtoYYYYconfig variable โ that's what gets used to determine how to figure out the full year. Slay. โจ
Date::Manip 5.xx vs 6.00, aka the glow-up ๐ญ
Date::Manip 5.xx handled ISO 8601 dates in a less rigid fashion, and deviated from the specification in several formats. As of 6.00, the specification is followed much more closely, so that all of the date formats included in it should produce valid dates. This changes, in a backwards incompatible way, the way a few strings get interpreted as dates. Not me breaking your code, it's for your own good bestie ๐ซถ
- As of 6.00, a two-digit date will be treated as
CC. Previously, it was treated asYY. - A six-digit date will be treated as
YYMMDD. Previously, it was treated asYYYYMM. - Previously, dashes were treated as optional in many cases. According to the specification, dates may be written in expanded form (with all dashes present) or abbreviate form (with no dashes). As of 6.00 this is the behavior, so the formats
YYMMDDandYY-MM-DDare allowed, as per the specification, but the formatYY-MMDDis NOT allowed (though it was previously). ๐
The Www-D formats, explained with love ๐ง
Okay so the Www-D formats require a bit of explanation, bestie, buckle up. ๐
According to the specification, the date:
1996-w02-3
refers to the day with an ordinal number of 3 within the calendar week in the 2nd week of 1996.
In the specification, the days of the week are numbered from 1 to 7 (Monday to Sunday), and the week always begins on Monday. So day 1 (Monday) is always the first day of the week, day 2 (Tuesday) is always the second day of the week, etc. Very rigid, very rules-based. ๐
In Date::Manip, the constraint that the week must start with Monday is relaxed, allowing the week to begin with Sunday (a far more common start of the week in calendars, at least in some parts of the world). We're being flexible, we're being global, we're thriving ๐โจ
But this presents a problem ๐ญ โ the above date could be interpreted as Wednesday (day 3) of the 2nd week of 1996, or as the 3rd day of the 2nd week of 1996 (which would normally be Wednesday, but would be Tuesday if the week begins on Sunday).
As of Date::Manip 6.00, the above date will be interpreted as the 3rd day of the 2nd week. This is a reversal from Date::Manip 5.xx, but I believe it's what the specification would require. For more information, refer to the Date::Manip::Changes document. ๐
Common date formats ๐ธ
Date::Manip supports a number of common date formats. The following fields may be included in a date:
YYโ 2-digit representation of the yearYYYYโ 4-digit representation of the yearMโ 1- or 2-digit representation of the monthMMโ 2-digit representation of the monthDโ 1- or 2-digit representation of the dayDDโ 2-digit representation of the daymmmโ The abbreviated or full month name (i.e.Jan)
The following date formats are supported:
Format Notes Examples
M/D 1,2,3 3/5
M/D/YY 1 3/5/09
M/D/YYYY 1 3/5/2009
YYYY/M/D 2009/3/5
mmm/D Mar/5
mmm/D/YY Mar/5/09
mmm/D/YYYY Mar/5/2009
D/mmm 5/Mar
D/mmm/YY 5/Mar/09
D/mmm/YYYY 5/Mar/2009
YYYY/mmm/D 2009/Mar/5
mmmD Mar5
mmmDDYY 4 Mar0509
mmmDDYYYY Mar052009
Dmmm 5Mar
DmmmYY 5Mar09
DmmmYYYY 5Mar2009
YYYYmmmD 2009Mar5
mmmD YY Mar5 09
mmmD YYYY Mar5 2009
Dmmm YY 5Mar 09
Dmmm YYYY 5Mar 2009
mmm/D YY Mar/5 09
mmm/D YYYY Mar/5 2009
D/mmm YY 5/Mar 09
D/mmm YYYY 5/Mar 2009
YY mmmD 09 Mar5
YYYY mmmD 2009 Mar5
YY Dmmm 09 5Mar
YYYY Dmmm 2009 5Mar
YY mmm/D 09 Mar/5
YYYY mmm/D 2009 Mar/5
YY D/mmm 09 5/Mar
YYYY D/mmm 2009 5/Mar
YYYY:MM:DD 2010:01:15 (EXIF format)
mmmYYYY 4 Jun 2010
YYYYmmm 4 2010 June
mmm/YYYY 4 Jun/2010
YYYY/mmm 4 2010/Jun
In the formats above, the slash (/) can be replaced by any of the valid separators: whitespace, slash (/), period (.), or dash (-). ๐ฆ
The dash, though allowed, is discouraged since it may conflict with an ISO 8601 format. For example, the formatMM/DD/YYis just fine, butMM-DD-YYdoes not work since it conflicts withYY-MM-DD. To be safe, if-is used as a separator in a non-ISO format, they should be turned into/before calling the Date::Manip routines, or you should use thenoiso8601option with theparseorparse_datemethods. ๐
No matter what separator is used, the same separator must be used throughout the date. For example, MM/DD/YY is valid and MM.DD.YY is also valid, but MM/DD.YY is NOT valid. Consistency is the vibe check bestie โจ
Notes ๐
- With these formats, Americans tend to write month first, but many other countries tend to write day first. The latter behavior can be obtained by setting the config variable
DateFormatto something other than"US". - The dot (
.) separator may not be used in theM/Dformat since it will be interpreted as theH12,H+format described below. - The
M/Dformat should not use the period (.) separator as that will incorrectly match theHH,H+time format. - Historically, I have not supported partial dates (i.e. dates that were not fully specified), but it has been argued that something like
'Jun 1910'would be interpreted by almost everyone as a day in June of 1910 instead of June 19, 2010. And it has been shown that in some applications, dates are specified in that way. I have added the new config variableFormat_MMMYYYYwhich will change this.
If this variable is not set, the formats allowed are:
mmmDDYY
If it is set, the formats allowed are:
mmmYYYY
YYYYmmm
The day of week may not be included with these formats. When parsing a full date/time, if Format_MMMYYYY is set to 'first', it returns the 1st of the month at midnight. If it is set to 'last', it returns the last day at 23:59:59. If parsing only a date, it will be set to the first or last day of the month at midnight. ๐
These formats explicitly set the date, but not the time. The default time is determined by the DefaultTime config variable. โฐ
Less common date formats ๐
The following formats are also supported by Date::Manip:
DoWโ the day of the week of the current week</p>. So likeFriday, orFriday at 12:40if you want a time in there too ๐MMM Nth [YYYY],Nth MMM [YYYY],YYYY MMM Nth,YYYY Nth MMMโ every which way you wanna stack month / day number / year, bestie ๐:
Dec 1st 1970
1st Dec 1970
1970 Dec 1st
1970 1st Dec
next/prev DoWโ the next or last occurrence of DoW:
next Friday
last Friday at 12:40
next/last week/month/yearโ the day one week/month/year from now, or in the past ๐ฐ๏ธ:
next week
last month at 15:00
last day in MMM [YYYY]โ the last day of the month, periodt:
last day in October
last day in October 1996
last DoW in MMM [YYYY]โ the last DoW of the month:
last Tuesday in October
last Tuesday in October 1996
last DoW in YYYYโ the last DoW of the year:
last Tuesday in 1997
NOTE:"last DoW"doesn't work in English ๐ญ because the word"last"is used for both this expression and for"prev DoW", which gets parsed first."last DoW"MAY work in other languages tho ๐
Nth DoW in MMM [YYYY]โ the Nth DoW of the month:
3rd Tuesday in October
3rd Tuesday in October 1996
Nth DoW [YYYY]โ the Nth DoW of the year:
22nd Sunday
22nd Sunday in 1996
Nth day in MMM [YYYY]โ the Nth day of the month:
1st day of February
1st day of February 2012
DoW weekโ British ๐ฌ๐ง, same energy as"in 1 week on DoW":
Monday week
DoW week N [YYYY],Dow Nth week [YYYY]โ like:
Sunday week 22
Sunday 22nd week
These refer to the day of week of the Nth week of the year.
Nthโ like:
12th
This refers to the Nth day of the current month.
ok so heads up, the formats "Sunday week 22" and "22nd Sunday" give different behaviors and that's not a bug, that's just how it is ๐
"Sunday week 22" returns the Sunday of the 22nd week of the year, based on how week 1 is defined. ISO 8601 defines week one to contain Jan 4, so "Sunday week 1" might be the first or second Sunday of the current year, or the last Sunday of the previous year. Meanwhile "22nd Sunday" gives the actual 22nd time Sunday occurs in a given year, regardless of the definition of a week. iykyk ๐ซ
โจ Special date strings โจ
Most languages have strings you can use to specify the date (relative to today, obvi). In English, those include:
today
tomorrow
yesterday
There's also support for the British formats ๐ฌ๐ง:
today week
tomorrow week
yesterday week
which refer to one week after today/tomorrow/yesterday respectively. Other languages have similar strings too, bestie ๐
๐ Holidays ๐
You can parse holiday names as dates (timezones included, yes really ๐). For example:
Christmas
Christmas 2010
Christmas 2010 at noon
Christmas 2010 at noon PST
Saturday Christmas 2010 at noon
In all of the formats (except for the ISO 8601 formats), the day of week ("Friday") can be entered anywhere in the date and it will be checked for accuracy โ
. In other words,
"Tue Jul 16 1996 13:17:00"
will work, but
"Jul 16 1996 Wednesday 13:17:00"
will not ๐ซ (because Jul 16, 1996 is Tuesday, not Wednesday, and we don't do lies here).
๐ A NOTE ABOUT FOREIGN LANGUAGE DATES ๐
ok so real talk bestie: Date::Manip does have some support for parsing dates in foreign languages, but it must be noted that the formats supported are largely based on English equivalents. ๐
There are probably many different dates that are perfectly valid, and in common usage, in other languages, which do not have an equivalent in the English language, and unfortunately, Date::Manip will probably not parse these. ๐ญ
You are free to send these to me, and I'll see if there is a way to add them in, but I do not guarantee anything ๐ซถ. Without having a full-blown language parser (or at least the portion of the language that is devoted to calendar and time), most of these formats will simply not be supportable. fr fr.
โจ VALID TIME FORMATS โจ
Okay bestie, so this part is all about time-only strings โ the ones that just give you the hour/minute/second fields and nothing else. Date::Manip supports a whole bunch of them, and they break down into a few categories. ๐
๐ธ ISO 8601 times ๐ธ
An ISO 8601 time can be complete or truncated. And listen โ Date::Manip treats some of them as complete even though the spec itself calls them truncated. We love a relaxed queen. ๐
A time can include these fields:
HHโ 2-digit representation of the hourMNโ 2-digit representation of the minutesSSโ 2-digit representation of the secondsH+โ 1+ digit representation of fractional hoursM+โ 1+ digit representation of fractional minutesS+โ 1+ digit representation of fractional seconds
Here's which time formats Date::Manip counts as complete. In the examples we're using the time 12:30:15:
HHMNSSโ note 2 โ e.g.123015HH:MN:SSโ e.g.12:30:15HHMNSS,S+โ e.g.123015,5HH:MN:SS,S+โ e.g.12:30:15,5โ fractional seconds are ignoredHHMN,M+โ e.g.1230,25HH:MN,M+โ e.g.12:30,25โ this is 12:30:00 + 0.25 minutesHH,H+โ e.g.12,5โ this is 12:00:00 + 0.5 hours, so this is equivalent to 12:30:00-MNSSโ note 1 โ e.g.-3015-MN:SSโ e.g.-30:15--SSโ note 1 โ e.g.--15-MNSS,S+โ note 1 โ e.g.-3015,5-MN:SS,S+โ e.g.-30:15,5-MN,M+โ note 1 โ e.g.-30,25--SS,S+โ note 1 โ e.g.--15,5HHMNโ note 3 โ e.g.1230HH:MNโ e.g.12:30
And these ones are truncated:
HHโ e.g.12-MNโ e.g.-30
Notes, because context is everything bestie: 1. These formats are considered truncated in the standard, but since they do include (or imply, using the current time for defaults) all of the fields, and since they do not introduce any parsing complexities, the standard is relaxed, and they are treated as complete. 2. TheHHMNSSformat will not be correctly parsed since it is impossible to distinguish between it andYYMMDD. In order to parse an all-digit time, add the string,0to the end to force it to be interpreted as a time or include time zone information (either a zone name or abbreviation... an offset will not work in this case). 3. TheHH:MNformat will be treated as complete, even though it is incomplete due to missing the seconds. In real life, expressing a time in theHH:MNformat is very common, and is regarded as complete, and might include time zone information.
ISO 8601 times can be followed by a time zone โ unless they're truncated. Truncated times may not include a timezone. ๐ซ And Date::Manip relaxes the constraints on the time zone format, allowing any of the methods used to specify a time zone: time zone name, abbreviation, or offset. The time zone can be separated from the time by a space, but it doesn't have to be.
Another relaxed constraint: the fractional part can be specified using a period. In other words, these are equivalent:
12:30,25
12:30.25
Lowkey important โ and the spec says this too โ using a negative time zone offset may cause confusion. As well as being visually confusing, it may not be parsed correctly. For example, this time:123005-0300may not be parsed correctly. When using an offset time zone, you should always use the colon separators in the time:12:30:05-0300
๐ Other time formats ๐
A time can include any of these fields:
H24โ 1- or 2-digit representation of the hour (0-23)H12โ 1- or 2-digit representation of the hour (1-12)MNโ 2-digit representation of the minutesSSโ 2-digit representation of the secondsH+โ 1+ digit representation of fractional hoursM+โ 1+ digit representation of fractional minutesS+โ 1+ digit representation of fractional secondsAMโ a language specific AM/PM string
These are the time formats that are accepted:
H24:MN:SSโ e.g.17:30:15H12:MN:SS AMโ e.g.5:30:15 PMH12:MN:SSH24:MN:SS,S+โ e.g.17:30:15,5H12:MN:SS,S+ AMโ e.g.5:30:15,5 PMH12:MN:SS,S+โ fractional seconds are ignoredH24:MN,M+โ e.g.17:30,25H12:MN,M+ AMโ e.g.5:30,25 PMH12:MN,M+โ this is 17:30:00 + 0.25 minutesH24,H+โ e.g.17,5H12,H+ AMโ e.g.5,5 PMH12,H+โ this is 17:00:00 + 0.5 hours, so this is equivalent to 17:30:00H24:MNโ e.g.17:30H12:MN AMโ e.g.5:30 PMH12:MNH12 AMโ e.g.5 PM
The fractional part may be specified using a comma or a period. Fractional seconds may also be separated using a colon. And a language specific fractional separator may also be available for some languages. So basically, all of these are equivalent:
12:30:20,25
12:30:20.25
12:30:20:25
Some languages have alternate H:MN and MN:S separators. For example, one H:MN separator in French is h (the MN:S separator is still a colon), so these are equivalent:
12:30:00
12h30:00
Time zone information can be included immediately following the time. It can be separated by whitespace from the time, or it can be immediately adjacent. โจ
๐ฆ Special time strings ๐ฆ
Different languages may have some words which can be used to specify a certain time of day. In English, for example, these words are equivalent to the time listed:
noonโ12:00:00midnightโ00:00:00
So the following are equivalent:
Jan 2 2009 at noon
Jan 2 2009 12:00:00
There were two possible ways to interpret midnight. One was at the start of the day (00:00:00) and the other was at the end of the day (24:00:00, which would actually mean at 00:00:00 of the following day). The first has been used to maintain backwards compatibility with Date::Manip 5.xx. ๐ซถ
Other languages have similar strings.
In most languages, a word similar to "at" may precede the time (this does NOT apply to ISO 8601 time formats). This word (which must be separate from all other parts of the date with whitespace) is optional, and the following are equivalent:
12:30
at 12:30
The times 12:00 am, 12:00 pm, and midnight are not well defined. Date::Manip uses the following convention:
midnight = 12:00am = 00:00:00
noon = 12:00pm = 12:00:00
and the day goes from 00:00:00 to 23:59:59. In other words, midnight is the beginning of a day rather than the end of one. The time 24:00:00 is also allowed (though it is automatically transformed to 00:00:00 of the following day). This gives the unusual result of parsing:
Wed Feb 8 2006 24:00:00
which gives the date of:
Thu Feb 9 2006 00:00:00
โจ VALID COMBINED DATE AND TIME FORMATS โจ
okay so bestie, sometimes a string isn't just a date OR just a time โ it's both at once, and there are like several whole categories of these. here's the rundown ๐
๐ฆ ISO 8601 combined date and time
a combined ISO 8601 date and time is a string that has a complete ISO 8601 date plus a complete or truncated ISO 8601 time. it can also have a timezone in there, but only if a complete time is included. no cap.
Date::Manip is lowkey chill and relaxes the rules on how you glue the two together. the time can be separated from the date by a space, a dash, or the letter T โ or you can just smush them together with literally nothing in between. ๐
when the time comes right after the date, or when the two are separated by a dash, the resulting string MUST be unambiguous. if the date has all its dashes in it (likeYY-MM-DDinstead ofYYMMDD) it's rarely ambiguous. but if the date has no dashes, the strings can get ambiguous, and in that case separating the date and time with a space or the letterTis useful (and maybe even necessary) to interpret it correctly. don't skip this part, it matters fr fr.
the DoY formats should always be separated from the time by something. they're visually confusing if you don't โ it's giving chaos. ๐ญ
time zone info can go right after a complete time. it may not be included if no time is given, or if a truncated time is included. the time zone can be separated from the time with whitespace, or it can sit immediately adjacent to it (since the ISO 8601 spec allows that in some cases). ๐
๐ธ Non-ISO 8601 combined date and time
a date from any of the non-ISO 8601 formats above can be combined with any of the non-ISO 8601 time formats above, in any combination, to form a valid combined date and time. mix and match, iconic behavior. โจ
๐ฅ Deltas
dates are often specified as a delta from now. like, "in 2 days". periodt.
most valid deltas can be used to specify a date, and that date is defined as that delta added to now. go check the Date::Manip::Delta docs for the full list of valid delta formats. ๐
if the delta itself doesn't include a time part, you can specify the time explicitly. for example:
in 3 days at 12:00:00
in 3 days at 12:00:00 PST
these take the delta part in 3 days, add it to the current time, and then set the time to 12:00:00. chef's kiss. ๐
it is NOT allowed to include an explicit time if any time segment was already included in the delta. so this next one is invalid, bestie, do not do this: in 3 days 2 hours at 12:00:00
one more format that's supported: include only week (or higher) components in the delta, and set the day of week. like so:
Friday in 2 weeks
in 2 weeks on Friday
Friday 2 weeks ago
2 weeks ago on Friday at 13:45
these first apply the delta (of weeks, months, and years) to the current time, and then set the day to the given day-of-week in that week. ๐
๐ Special date and time strings
most languages have strings you can use to specify the full date and time (relative to the current date and time). in English, that includes:
now
they may also have a timezone attached:
now PST
โญ Additional combined date and time formats
these formats are also supported:
epoch SECS
The number of seconds since the epoch
(Jan 1, 1970 00:00:00 GMT). SECS may
be negative to give time before the
epoch.
or
epoch SECS TIMEZONE
a couple of notes ๐ซถ
- Commas may be included in all date formats arbitrarily (except for ISO 8601 formats, where they may only be included when allowed by the specification).
- The time/time zone is removed from the date before the date is parsed, so the time may appear before or after the date, or between any two parts of the date. wild, right? ๐
- The time and the zone do not need to be adjacent, so this string:
Jan 21 17:13:27 2010 -0400
will work. but if the timezone is separate from the date, it MUST be separated from any other portion of the date by whitespace. remember that. ๐
- Certain words such as
"on","in","at","of", etc. which commonly appear in a date or time are ignored (except in ISO 8601 formats). they're just filler, we love them anyway. ๐
๐ PRINTF DIRECTIVES ๐
okay so bestie, this is where you get to accessorize your dates ๐
โ every directive below gets swapped out for actual info from your date object. All of these assume the Use_POSIX_Printf config variable is unset. If it is set, skip on down to the POSIX PRINTF DIRECTIVES section instead.
โจ Year โจ
%yโ year โ00to99%Yโ year โ0001to9999
โจ Month, Week โจ
%mโ month of year โ01to12%fโ month of year โ" 1"to"12"%b,%hโ month abbreviation โJantoDec%Bโ month name โJanuarytoDecember
โจ Day โจ
%jโ day of the year โ001to366%dโ day of month โ01to31%eโ day of month โ" 1"to"31"%vโ weekday abbreviation โ" S"," M"," T", ...%aโ weekday abbreviation โSuntoSat%Aโ weekday name โSundaytoSaturday%wโ day of week โ1to7(1=Monday)%Eโ day of month with suffix โ1st,2nd,3rd...
โจ Hour โจ
%Hโ hour โ00to23%kโ hour โ" 0"to"23"%iโ hour โ" 1"to"12"%Iโ hour โ01to12%pโAMorPM
โจ Minute, Second, Time zone โจ
%Mโ minute โ00to59%Sโ second โ00to59%Zโ time zone abbreviation โEDT%zโ time zone as GMT offset โ+0100(see Note 4)%Nโ time zone as GMT offset โ+01:00:00
โจ Epoch (see NOTE 3 below) โจ
%sโ seconds from1/1/1970 GMTโ negative if before%oโ seconds from1/1/1970in the current time zone
โจ Date, Time โจ
%cโ%a %b %e %H:%M:%S %YโFri Apr 28 17:23:15 1995%C,%uโ%a %b %e %H:%M:%S %Z %YโFri Apr 28 17:25:57 EDT 1995%gโ%a, %d %b %Y %H:%M:%S %ZโFri, 28 Apr 1995 17:23:15 EDT%Dโ%m/%d/%yโ04/28/95%xโ%m/%d/%yor%d/%m/%yโ04/28/95or28/04/95(depends on theDateFormatvariable)%lโ date inls(1)format (see NOTE 1 below)%b %e %H:%MโApr 28 17:23(*)%b %e %YโApr 28 1993(*)
%rโ%I:%M:%S %pโ05:39:55 PM%Rโ%H:%Mโ17:40%T,%Xโ%H:%M:%Sโ17:40:58%Vโ%m%d%H%M%yโ0428174095%Qโ%Y%m%dโ19961025%qโ%Y%m%d%H%M%Sโ19961025174058%Pโ%Y%m%d%H:%M:%Sโ1996102517:40:58%Oโ%Y-%m-%dT%H:%M:%Sโ1996-10-25T17:40:58%Fโ%A, %B %e, %YโSunday, January 1, 1996%Kโ%Y-%jโ1997-045
โจ Special Year/Week formats (see NOTE 2 below) โจ
%Gโ year, Monday as first day of week โ0001to9999%Wโ week of year, Monday as first day of week โ01to53%Lโ year, Sunday as first day of week โ0001to9999%Uโ week of year, Sunday as first day of week โ01to53%Jโ%G-W%W-%wโ1997-W02-2
โจ Other formats โจ
%nโ insert a newline character%tโ insert a tab character%%โ insert a%character%+โ insert a+character
All other characters are currently unused, but may be used in the future. They currently insert the character following the %.
The following multi-character formats also exist:
โจ Extended formats โจ
%<A=NUM>,%<a=NUM>,%<v=NUM>โ these return the NUMth value of the%A,%a, and%vformats respectively. In English, that would yield:
%<A=2> => Tuesday
%<a=2> => Tue
%<v=2> => T
NUM must be in the range 1-7.
%<B=NUM>,%<b=NUM>โ these return the NUMth value of the%Band%bformats respectively. In English, that would yield:
%<B=2> => February
%<b=2> => Feb
NUM must be in the range 1-12 (or 01-12).
%<p=NUM>โ these return the NUMth value of the%pformat. In English, that would yield:
%<p=1> => AM
%<p=2> => PM
NUM must be in the range 1-2.
%<E=NUM>โ these return the NUMth value of the%Eformat. In English, that would yield:
%<E=1> => 1st
%<E=53> => 53rd
NUM must be in the range 1-53.
If a lone percent is the final character in a format, it is ignored.
The formats used in this routine were originally based on date.pl (version 3.2) by Terry McGonigal, as well as a couple taken from different versions of the Solaris date(1) command. Also, several have been added which are unique to Date::Manip.
๐ธ NOTE 1 ๐ธ
The ls format (%l) applies to date within the past OR future 6 months! Any date that is before the date NOW - 6 months, or that is on or after the date NOW + 6 months will have the year printed out.
The later time must be on or after so that there is no ambiguity. If it is now 2000-06-06-12:00:00, then the date 1999-12-06-12:00:00 will be written as "Dec 6 12:00" but the date 2000-12-06-12:00:00 will be written as "Dec 6 2000".
๐ธ NOTE 2 ๐ธ
The %U, %W, %L, %G, and %J formats are used to support the ISO-8601 format: YYYY-wWW-D. In this format, a date is written as a year, the week of the year, and the day of the week. Technically, the week may be considered to start on any day of the week, but Sunday and Monday are both common choices, so both are supported.
The %W and %G formats return the week-of-year and the year treating weeks as starting on Monday.
The %U and %L formats return the week-of-year and the year treating weeks as starting on Sunday.
Most of the time, the %L and %G formats returns the same value as the %Y format, but there is a problem with days occurring in the first or last week of the year.
The ISO-8601 representation of Jan 1, 1993 written in the YYYY-wWW-D format is actually 1992-W53-5. In other words, Jan 1 is treated as being in the last week of the preceding year. Depending on the year, days in the first week of a year may belong to the previous year, and days in the final week of a year may belong to the next year. The week is assigned to the year which has most of the days. For example, if the week starts on Sunday, then the last week of 2003 is 2003-12-28 to 2004-01-03. This week is assigned to 2003 since 4 of the days in it are in 2003 and only 3 of them are in 2004. The first week of 2004 starts on 2004-01-04.
The %U and %W formats return a week-of-year number from 01 to 53. %L and %G return the corresponding year, and to get this type of information, you should always use the (%W,%G) combination or (%U,%L) combination. %Y should not be used as it will yield incorrect results.
%J returns the full ISO-8601 format (%G-W%W-%w).
๐ธ NOTE 3 ๐ธ
The %s and %o formats return negative values if the date is before the start of the epoch. Other Unix utilities would return an error, or a zero, so if you are going to use Date::Manip in conjunction with these, be sure to check for a negative value.
๐ธ NOTE 4 ๐ธ
The %z format returns the offset in the RFC 822 specified format +0500. Most offsets are full hour amounts, so this is not a problem, but some offsets are irregular (+05:17:30). In this case, the string returned is +051730 which isn't RFC 822 compliant, but since RFC 822 ignores this situation, I had to decide between returning an incorrect value, or breaking strict compliance, and I chose the second option.
๐ POSIX PRINTF DIRECTIVES ๐
okay so real talk bestie, a couple of the printf directives in Date::Manip::Date::printf do not match the standard POSIX strftime directives, and that's on purpose. For backward compatibility reasons the author is not gonna change that. BUT โ plot twist โ you can set the Use_POSIX_Printf config variable to 1 and get the POSIX formats instead of the default ones. โจ
When that variable is set, most of the printf formats described above still apply, except the formats get swapped out for their POSIX value:
%Cโ The century number (first two digits of the year).%Fโ This is equivalent to%Y-%m-%d%lโ The hour (12-hour clock) padded with spaces%Pโ Either'am'or'pm'.%uโ Day of week from1-7with Monday being1.%Gโ Similar to the%Gformat described above, but strictly adheres to the ISO 8601 week definition where the first week of the week is Monday and the first week of the year contains Jan 4.%gโ Identical to%gbut only has the last two digits of the year.%Wโ Similar to the%Wformat described above, but with Monday being the first day of the week and the first Monday in the year being the first day of the first week.%Vโ Similar to the%Wformat described above, but strictly adheres to the ISO 8601 week definition where the first week of the week is Monday and the first week of the year contains Jan 4.%Lโ Thestrftimefunction does not have a%Ldirective. It's been set anyway to be similar to the%Lformat above, except using Sunday as the first day of the week and the first week of the year contains Jan 4 (so this is the equivalent of%Gbut with Sunday being the first day of the week).%Uโ Similar to the%Uformat described above but with Sunday being the first day of the week and the first Sunday being the first day of the first week.%Jโ Thestrftimefunction does not have a%Jdirective, but in order to support the ISO 8601YYYY-wWW-Dformat, this is equivalent to'%G-W%V-%w'.
Note 1: The default (i.e. non-POSIX) Date::Manip printf formats are defined so that%Gand%Wuse the exact same definition of week, and likewise%Land%Uuse the same definition of weeks. This means you can use them to write a date in an ISO 8601YYYY-wWWformat. In the POSIXstrftimedefinitions,%Gand%Vwork together, but there is no equivalent pair for Sunday being the first day of the week.
The following POSIX strftime directives are not yet supported (though they may be in a future version of Date::Manip ๐). These will continue to return the values listed above from the non-POSIX formats.
%c,%x,%Xโ Thestrftimeformat give the preferred date/time representations in the current locale.
Currently Date::Manip does not make use of locale information so there is no locale-specific format.
The default format (which is the preferred date and time format in America) is used in all locales.
%E,%Oโ Modifiers to create additional directives.%+โ Date and time in the format of thedatecommand
๐ KNOWN BUGS ๐
None known. ๐ iconic behaviour, honestly.
๐ซถ BUGS AND QUESTIONS ๐ซถ
Please refer to the Date::Manip::Problems documentation for information on submitting bug reports or questions to the author.
๐ SEE ALSO ๐
Date::Manip- main module documentation
๐ LICENSE ๐
This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
๐ธ AUTHOR ๐ธ
Sullivan Beck (https://github.com/SBECK-github/)
and that's a wrap on the whole page bestie, we did it ๐ this one came from the perl v5.42.3 docs, dated 2026-09-01, and it's literally the Date::Manip::Date(3) manpage in its full glory. go forth and format your dates, no cap ๐โจ
๐ฆ where this page comes from
- fedora 43: perl-Date-Manip 7.00-1.fc43 ยท GPL-1.0-or-later OR Artistic-1.0-Perl
- fedora 44: perl-Date-Manip 7.00-1.fc44 ยท GPL-1.0-or-later OR Artistic-1.0-Perl
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms