Date::Manip::DM6(3)

โœจ NAME โœจ

Date::Manip::DM6 โ€” Date manipulation routines. This is the manual page for Date::Manip::DM6(3) from User Contributed Perl Documentation. It's literally the DM6 era of Date::Manip, and it's here to help you parse, format, and calculate dates like a main character. ๐Ÿ’…


๐ŸŒธ SYNOPSIS ๐ŸŒธ

okay bestie, here's the whole vibe of how you call these routines. copy/paste energy, no cap:

   use Date::Manip;

   $version = DateManipVersion($flag);

   Date_Init("VAR=VAL","VAR=VAL",...);

   $date = ParseDate(\@args [,@opts]);
   $date = ParseDate($string [,@opts]);
   $date = ParseDate(\$string [,@opts]);

   $date = ParseDateString($string [,@opts]);

   $date = ParseDateFormat($format,$string);

   @date = UnixDate($date,@format);
   $date = UnixDate($date,@format);

   $delta = ParseDateDelta(\@args   [,$mode]);
   $delta = ParseDateDelta($string  [,$mode]);
   $delta = ParseDateDelta(\$string [,$mode]);

   @str = Delta_Format($delta, [$mode,] $dec,@format);
   $str = Delta_Format($delta, [$mode,] $dec,@format);

   $recur = ParseRecur($string,$base,$date0,$date1,$flags);
   @dates = ParseRecur($string,$base,$date0,$date1,$flags);

   $flag = Date_Cmp($date1,$date2);

   $d = DateCalc($d1,$d2 [,$errref] [,$mode]);

   $date = Date_SetTime($date,$hr,$min,$sec);
   $date = Date_SetTime($date,$time);

   $date = Date_SetDateField($date,$field,$val [,$nocheck]);

   $date = Date_GetPrev($date,$dow,$today,$hr,$min,$sec);
   $date = Date_GetPrev($date,$dow,$today,$time);

   $date = Date_GetNext($date,$dow,$today,$hr,$min,$sec);
   $date = Date_GetNext($date,$dow,$today,$time);

   $name = Date_IsHoliday($date);
   @name = Date_IsHoliday($date);

   $listref = Events_List($date);
   $listref = Events_List($date0,$date1);

   $date = Date_ConvTZ($date,$from,$to);

   $flag = Date_IsWorkDay($date [,$flag]);

   $date = Date_NextWorkDay($date,$off [,$time]);

   $date = Date_PrevWorkDay($date,$off [,$time]);

   $date = Date_NearestWorkDay($date [,$tomorrowfirst]);

quick note before the next batch of signatures: in the following routines, $y may be entered as either a 2 or 4 digit year (it will be converted to a 4 digit year based on the variable YYtoYYYY described below). Month and day should be numeric in all cases. ๐Ÿ—“๏ธโœจ

   $day = Date_DayOfWeek($m,$d,$y);
   $secs = Date_SecsSince1970($m,$d,$y,$h,$mn,$s);
   $secs = Date_SecsSince1970GMT($m,$d,$y,$h,$mn,$s);
   $days = Date_DaysSince1BC($m,$d,$y);
   $day = Date_DayOfYear($m,$d,$y);
   ($y,$m,$d,$h,$mn,$s) = Date_NthDayOfYear($y,$n);
   $days = Date_DaysInYear($y);
   $days = Date_DaysInMonth($m,$y);
   $wkno = Date_WeekOfYear($m,$d,$y,$first);
   $flag = Date_LeapYear($y);
   $day = Date_DaySuffix($d);
   $tz = Date_TimeZone();

๐ŸŽ€ ROUTINES ๐ŸŽ€

DateManipVersion

$version = DateManipVersion($flag);

Returns the version of Date::Manip. If $flag is non-zero, timezone information is also returned. ๐ŸŒโœจ

Date_Init

Date_Init("VAR=VAL","VAR=VAL",...);

The Date_Init function is used to set any of the Date::Manip configuration variables described in the Date::Manip::Config document.

The strings to pass in are of the form "VAR=VAL". Any number may be included and they can come in any order. VAR may be any configuration variable. VAL is any allowed value for that variable. For example, to switch from English to French and use non-US format (so that 12/10 is Oct 12), do the following:

   Date_Init("Language=French","DateFormat=non-US");

Note that variables are parsed in the order they are given, so "DateFormat=non-US", "ConfigFile=./manip.cnf" may not give the expected result. To be safe, ConfigFile should always appear first in the list. ๐Ÿšจ

ParseDate

$date = ParseDate(\@args [,@opts]);
$date = ParseDate($string [,@opts]);
$date = ParseDate(\$string [,@opts]);

This takes an array or a string containing a date and parses it. When the date is included as an array (for example, the arguments to a program) the array should contain a valid date in the first one or more elements (elements after a valid date are ignored). Elements containing a valid date are shifted from the array. The largest possible number of elements which can be correctly interpreted as a valid date are always used. If a string is entered rather than an array, that string is tested for a valid date. The string is unmodified, even if passed in by reference. ๐Ÿ”

The ParseDate routine is primarily used to handle command line arguments. If you have a command where you want to enter a date as a command line argument, you can use Date::Manip to make something like the following work:

   mycommand -date Dec 10 1997 -arg -arg2

No more reading man pages to find out what date format is required in a man page. iconic. ๐Ÿ’…

The @opts argument may contain values that can be passed to the "Date::Manip::Date::parse" method.

Historical note: this is originally why the Date::Manip routines were written (though long before they were released as the Date::Manip module). I was using a bunch of programs (primarily batch queue managers) where dates and times were entered as command line options and I was getting highly annoyed at the many different (but not compatible) ways that they had to be entered. Date::Manip originally consisted of basically 1 routine which I could pass "@ARGV" to and have it remove a date from the beginning. ๐Ÿ“œ

ParseDateString

$date = ParseDateString($string [,@opts]);

This parses a string containing a date and returns it. Refer to the Date::Manip::Date documentation for valid date formats. The date returned is in the local time zone. ๐Ÿ•ฐ๏ธ

The @opts argument may contain values that can be passed to the "Date::Manip::Date::parse" method.

ParseDateFormat

$date = ParseDateFormat($format,$string);

This parses a string containing a date based on a format string and returns the date. Refer to the Date::Manip::Date documentation for the parse_format method for more information. The date returned is in the local time zone. ๐ŸŒ

UnixDate

$out = UnixDate($date,$in);
@out = UnixDate($date,@in);

This takes a date and a list of strings containing formats roughly identical to the format strings used by the UNIX date(1) command. Each format is parsed and an array of strings corresponding to each format is returned. โœจ

The formats are described in the Date::Manip::Date document.

ParseDateDelta

$delta = ParseDateDelta(\@args   [,$mode]);
$delta = ParseDateDelta($string  [,$mode]);
$delta = ParseDateDelta(\$string [,$mode]);

In the first form, it takes an array and shifts a valid delta from it. In the other two forms, it parses a string to see if it contains a valid delta.

A valid delta is returned if found. Otherwise, an empty string is returned. ๐Ÿซ™

The delta can be converted to 'exact', 'semi', or 'approx' using the Date::Manip::Delta::convert method if $mode is passed in.

Delta_Format

$out = Delta_Format($delta [,$mode], $dec,$in);
@out = Delta_Format($delta [,$mode], $dec,@in);

This is similar to the UnixDate routine except that it extracts information from a delta. ๐Ÿ”

When formatting fields in a delta, the Date::Manip 6.00 formats have changed and are much more powerful. The old 5.xx formats are still available for the Delta_Format command for backward compatibility. These formats include:

   %Xv  : print the value of the field X

   %Xd  : print the value of the field X and all
          smaller units in terms of X

   %Xh  : print the value of field X and all
          larger units in terms of X

   %Xt  : print the value of all fields in
          terms of X

These make use of the $mode and $dec arguments to determine how to format the information.

$dec is an integer, and is required, It tells the number of decimal places to use. ๐Ÿ”ข

$mode is either "exact", "semi", or "approx" and defaults to "exact" if it is not included.

In "exact" mode, only exact relationships are used. This means that there can be no mixing of the Y/M, W/D, and H/MN/S segments (for non-business deltas, or Y/M, W, and D/H/MN/S segments for business deltas) because there is no exact relation between the fields of each set.

In "semi" mode, the semi-approximate relationships are used so there is no mixing between Y/M and W/D/H/MN/S.

In "approx" mode, approximate relationships are used so all fields can mix.

The semi-approximate and approximate relationships are described in the Date::Manip::Delta manual.

So, in "exact" mode, with a non-business delta, and $dec = 2, the following are equivalent:

   old style    new style
   ---------    ---------
   %Xv          %Xv
   %hd          %.2hhs
   %hh          %.2hdh
   %ht          %.2hds
   %yd          %.2yyM

In "approximate" mode, the following are equivalent:

   old style    new style
   ---------    ---------
   %Xv          %Xv
   %hd          %.2hhs
   %hh          %.2hdh
   %ht          %.2hys
   %yd          %.2yys

If you want to use the new style formats in Delta_Format, use one of the calls:

   Delta_Format($delta, @in);
   Delta_Format($delta, undef, @in);

If the first element of @in is an integer, you have to use the 2nd form. ๐Ÿงฎ

The old formats will remain available for the time being, though at some point they may be deprecated.

DateCalc

$d = DateCalc($d1,$d2 [,\$err] [,$mode]);

This takes two dates, deltas, or one of each and performs the appropriate calculation with them. Dates must be a string that can be parsed by ParseDateString. Deltas must be a string that can be parsed by ParseDateDelta. Two deltas add together to form a third delta. A date and a delta returns a 2nd date. Two dates return a delta (the difference between the two dates). ๐Ÿง 

Since the two items can be interpreted as either dates or deltas, and since many strings can be interpreted as both a date or a delta, it is a good idea to pass the input through ParseDateDelta, if appropriate if there is any ambiguity. For example, the string "09:00:00" can be interpreted either as a date (today at 9:00:00) or a delta (9 hours). To avoid unexpected results, avoid calling DateCalc as:

   $d = DateCalc("09:00:00",$someothervalue);

Instead, call it as:

   $d = DateCalc(ParseDate("09:00:00"),$someothervalue);

to force it to be a date, or:

   $d = DateCalc(ParseDateDelta("09:00:00"),$someothervalue);

โ€ฆand DateCalc keeps going in part 2, bestie. hold that thought. ๐Ÿ’–

  • pro tip bestie: if you want a delta treated as a delta, run it through ParseDate first to force it. That way no surprises, no cap.
  • lowkey though, passing stuff through ParseDate is optional, because everything's treated as a date by default anyway. And honestly, for performance reasons, you're better off not calling ParseDate at all.
  • if there's zero ambiguity? skip it, again for performance. And if the delta is a business delta?? you definitely should NOT do this. ๐Ÿšซ
  • one more thing that's actually kinda important: when you're parsing dates, a delta can be interpreted as a date relative to now. But DateCalc will ALWAYS treat a delta as a delta, NOT a date. periodt. ๐Ÿ’…
  • for the deets on how the math actually goes down, peek at the Date::Manip::Calc documentation. ๐Ÿ“–
  • by default, math is done in exact mode. ๐ŸŽฏ
  • if you pass in two deltas, or a date and a delta, $mode can force the delta to be either business or non-business mode. If $mode is 0 or 1, the delta(s) go non-business. Otherwise, they're business deltas. And if $mode is passed in, it only gets used when the business/non-business state wasn't explicitly set in the delta itself. $mode can also be any of the modes talked about in the Date::Manip::Calc docs.
  • if you pass in two dates, $mode decides what kind of calculation happens:
    • by default โ†’ an exact delta is produced โœจ
    • if $mode is 1 โ†’ an approximate delta
    • if $mode is 2 โ†’ a business approximate (bapprox) mode calculation
    • if $mode is 3 โ†’ an exact business mode delta
  • if $err is passed in, it gets set to:
    • 1 if $d1 is not a delta or date
    • 2 if $d2 is not a delta or date
    • 3 if any other error happens
  • this argument is optional, but if you include it, it has to come before $mode.
nothing is returned if an error occurs. ๐Ÿ˜ญ

ParseRecur ๐Ÿ’–

$recur = ParseRecur($string [,$base,$date0,$date1,$flags]);
@dates = ParseRecur($string [,$base,$date0,$date1,$flags]);

this parses a string with a recurrence in it and hands you back either a fully specified recurrence, or a list of the dates it refers to. ๐Ÿ—“๏ธ

$string can be any of these forms:

FREQ
FREQ*FLAGS
FREQ*FLAGS*BASE
FREQ*FLAGS*BASE*DATE0
FREQ*FLAGS*BASE*DATE0*DATE1

where FREQ is a frequence (go read the Date::Manip::Delta docs, bestie), FLAGS is a comma separated list of flags, and BASE, DATE0, and DATE1 are date strings. The dates and flags can also be passed in as $base, $date0, $date1, and $flags โ€” and those will override anything sitting in $string. ๐Ÿ‘‘

in scalar context, you get the fully specified recurrence (or as much info as is available). In list context, you get a list of dates. simple as that. โœจ

Date_Cmp ๐Ÿฆ‹

$flag = Date_Cmp($date1,$date2);

takes two dates and compares them. Any dates that can be parsed will get compared. no drama. ๐Ÿ’…

Date_GetPrev ๐ŸŒธ

$date = Date_GetPrev($date,$dow, $curr [,$hr,$min,$sec]);
$date = Date_GetPrev($date,$dow, $curr [,$time]);
$date = Date_GetPrev($date,undef,$curr,$hr,$min,$sec);
$date = Date_GetPrev($date,undef,$curr,$time);

takes a date (any string that ParseDateString can parse) and finds the previous occurrence of either a day of the week, or a certain time of day. โฐ

it's documented in the "prev" method over in Date::Manip::Date, except that here, $time is a string (HH, HH:MN:, or HH:MN:SS), and $dow can be a string like "Fri" or "Friday". cute, right?

Date_GetNext ๐ŸŒˆ

$date = Date_GetNext($date,$dow, $curr [,$hr,$min,$sec]);
$date = Date_GetNext($date,$dow, $curr [,$time]);
$date = Date_GetNext($date,undef,$curr,$hr,$min,$sec);
$date = Date_GetNext($date,undef,$curr,$time);

similar to Date_GetPrev. basically its sibling. ๐Ÿ‘ฏ

Date_SetTime ๐ŸŽ€

$date = Date_SetTime($date,$hr,$min,$sec);
$date = Date_SetTime($date,$time);

takes a date (any string ParseDateString can parse) and sets the time inside that date. for example, one way to get the time for 7:30 tomorrow would be:

$date = ParseDate("tomorrow");
$date = Date_SetTime($date,"7:30");

$time is a string (HH, HH:MN, or HH:MN:SS). โฑ๏ธ

Date_SetDateField ๐Ÿ’œ

$date = Date_SetDateField($date,$field,$val);

takes a date and sets one of its fields to a new value. $field is any of the strings "y", "m", "d", "h", "mn", "s" (case insensitive) and $val is the new value. ๐Ÿ’ซ

Date_IsHoliday ๐ŸŽ‰

$name = Date_IsHoliday($date);
@name = Date_IsHoliday($date);

returns undef if $date isn't a holiday, or a string with the holiday's name otherwise (or a list of names in list context). An empty string is returned for an unnamed holiday. ๐Ÿคท

Date_IsWorkDay ๐Ÿ’ผ

$flag = Date_IsWorkDay($date [,$flag]);

returns 1 if $date is a work day. If $flag is non-zero, the time gets checked to see if it falls within work hours. It returns an empty string if $date isn't valid. ๐Ÿ˜ฌ

Events_List ๐Ÿ—“๏ธโœจ

$ref = Events_List($date);
$ref = Events_List($date,0      [,$flag]);
$ref = Events_List($date,$date1 [,$flag]);

this returns a list of events. If $flag isn't given, or equals 0, the list (returned as a reference) looks like the one from the Date::Manip::Date::list_events method with $format = "dates". The only difference is it's formatted a lil differently to stay backward compatible with Date::Manip 5.xx. ๐Ÿ‘ต

the data from the list_events method is:

( [DATE1, NAME1a, NAME1b, ...],
  [DATE2, NAME2a, NAME2b, ...],
  ...
)

the reference returned from Events_List (if $flag = 0) is:

[ DATE1, [NAME1a, NAME1b, ...],
  DATE2, [DATE2a, DATE2b, ...],
  ...
]

for example, if these events are defined:

2000-01-01 ; 2000-03-21  = Winter
2000-03-22 ; 2000-06-21  = Spring
2000-02-01               = Event1
2000-05-01               = Event2
2000-04-01-12:00:00      = Event3

then these examples show off the function:

Events_List("2000-04-01")
 => [ 2000040100:00:00, [ Spring ] ]

Events_List("2000-04-01 12:30");
 => [ 2000040112:30:00, [ Spring, Event3 ] ]

Events_List("2000-04-01",0);
 => [ 2000040100:00:00, [ Spring ],
      2000040112:00:00, [ Spring, Event3 ],
      2000040113:00:00, [ Spring ] ]

Events_List("2000-03-15","2000-04-10");
 => [ 2000031500:00:00, [ Winter ],
      2000032200:00:00, [ Spring ]
      2000040112:00:00, [ Spring, Event3 ]
      2000040113:00:00, [ Spring ] ]

if $flag is 1, you get a tally of how much time each event got. Time where two or more events apply is counted for both. ๐Ÿ’ฏ

Events_List("2000-03-15","2000-04-10",1);
 => { Event3 => +0:0:+0:0:1:0:0,
      Spring => +0:0:+2:4:23:0:0,
      Winter => +0:0:+1:0:0:0:0
    }

when $flag is 2, you get a more complex tally where no event is counted twice:

Events_List("2000-03-15","2000-04-10",2);
 => { Event3+Spring => +0:0:+0:0:1:0:0,
      Spring        => +0:0:+2:4:22:0:0,
      Winter        => +0:0:+1:0:0:0:0
    }

the hash has one element for each combination of events. ๐Ÿ”‘

in both of these cases, there may be a hash element with an empty string as the key, which holds the amount of time with no events active. (iconic little detail ngl)

Date_DayOfWeek ๐ŸŒž

$day = Date_DayOfWeek($m,$d,$y);

returns the day of the week (1 for Monday, 7 for Sunday). ๐Ÿ“†

Date_SecsSince1970 โณ

$secs = Date_SecsSince1970($m,$d,$y,$h,$mn,$s);

returns the number of seconds since Jan 1, 1970 00:00 (negative if the date is earlier) in the current timezone. ๐ŸŒ

Date_SecsSince1970GMT ๐ŸŒ

$secs = Date_SecsSince1970GMT($m,$d,$y,$h,$mn,$s);

returns the number of seconds since Jan 1, 1970 00:00 GMT (negative if the date is earlier). Note: the date is still given in the current timezone, NOT GMT. don't get it twisted bestie ๐Ÿ’…

Date_DaysSince1BC ๐Ÿ“œ

$days = Date_DaysSince1BC($m,$d,$y);

returns the number of days since Dec 31, 1BC. This includes the year 0001. ๐Ÿ›๏ธ

Date_DayOfYear ๐ŸŽฏ

$day = Date_DayOfYear($m,$d,$y);

returns the day of the year (1 to 366). โœจ

Date_NthDayOfYear ๐Ÿ”ข

($y,$m,$d,$h,$mn,$s) = Date_NthDayOfYear($y,$n);

returns the year, month, day, hour, minutes, and decimal seconds given a floating point day of the year. ๐Ÿงฎ

all arguments must be numeric. $n must be >= 1 and less than 366 on non-leap years and 367 on leap years.

NOTE: when $n is a decimal number, the results are non-intuitive perhaps. ๐Ÿ˜ญ Day 1 is Jan 01 00:00. Day 2 is Jan 02 00:00. Intuitively, you might think of day 1.5 as being 1.5 days after Jan 01 00:00, but that would mean Day 1.5 was Jan 02 12:00 (which is later than Day 2). The best way to think of this function is a time line starting at 1 and ending at 366 (in a non-leap year). In terms of a delta, think of $n as the number of days after Dec 31 00:00 of the previous year.

Date_DaysInYear ๐Ÿ—“๏ธ

$days = Date_DaysInYear($y);

returns the number of days in the year (365 or 366). ๐ŸŒˆ

Date_DaysInMonth ๐ŸŒ™

$days = Date_DaysInMonth($m,$y);

returns the number of days in the month. โœจ

Date_WeekOfYear ๐Ÿ“…

$wkno = Date_WeekOfYear($m,$d,$y,$first);

figures out the week number. $first is the first day of the week, which is usually 1 (Monday) or 7 (Sunday), but could be any number between 1 and 7 in practice.

NOTE: this routine should only be called in rare cases. Use printf with the %W, %U, %J, %L formats instead, because that will always return the correct values for week and year. ๐Ÿซถ

this routine returns a week between 0 and 53, which then has to be "fixed" 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. ๐Ÿคฏ

Date_LeapYear ๐Ÿธ

$flag = Date_LeapYear($y);

returns 1 if the argument is a leap year. Written by David Muir Sharnoff <muir@idiom.com> โœ๏ธ

Date_DaySuffix ๐Ÿ’ซ

$day = Date_DaySuffix($d);

adds st, nd, rd, th to a date (i.e. 1st, 22nd, 29th). Works for international dates. ๐ŸŒโœจ

Date_TimeZone ๐Ÿ•ฐ๏ธ๐Ÿ’–

$tz = Date_TimeZone;

Bestie, this one literally just figures out and hands you back the local time zone. It's giving "where am I right now?" energy. But if it cannot figure out the local time zone, you get this exact error:

ERROR: Date::Manip unable to determine Time Zone.

For the full tea, go read the Date::Manip::TZ documentation, specifically the DETERMINING THE LOCAL TIME ZONE section. ๐Ÿซถ


Date_ConvTZ ๐Ÿ”„๐ŸŒ

$date = Date_ConvTZ($date,$from,$to);

This one converts a date from one time zone to another. Important: the date MUST be in the format returned by ParseDate. No random vibes, okay? ๐Ÿ˜ญ

$from and $to each default to the local time zone. If you do pass them, they have to be any time zone or alias that Date::Manip understands. If something goes wrong, you get an empty string back. That's it. ๐Ÿ’…


Date_NextWorkDay ๐Ÿ“…โœจ

$date = Date_NextWorkDay($date,$off [,$time]);

Finds the day $off work days from now. If $time is passed in, we also have to take the time of day into account. Main character attention to detail, fr fr.

If $time is not passed in, day 0 is today (if today is a workday) or the next work day if it isn't. Either way, the time of day is unaffected. ๐Ÿ•ฐ๏ธ

If $time is passed in, day 0 is now (if now is part of a workday) or the start of the very next work day. Slay.


Date_PrevWorkDay โช๐ŸŒธ

$date = Date_PrevWorkDay($date,$off [,$time]);

Similar to Date_NextWorkDay. That's the whole vibe. ๐Ÿ’–


Date_NearestWorkDay ๐ŸŽฏ๐Ÿ“†

$date = Date_NearestWorkDay($date [,$tomorrowfirst]);

This looks for the work day nearest to $date. If $date is already a work day, it gets returned. Iconic, no notes. Otherwise, it looks forward or backwards in time 1 day at a time until a work day is found.

If $tomorrowfirst is non-zero (or if it's 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 $date is Wednesday, $date is returned.
  • If $date is Saturday, Friday is returned.
  • If $date is Sunday, Monday is returned.

If Wednesday is a holiday, Thursday is returned if $tomorrowfirst is non-nil, or Tuesday otherwise. Periodt. ๐Ÿ‘‘


For all of the functions which return a date, the format of the returned date is governed by the Printable config variable. If a date is returned, it is in the local time zone, NOT the time zone the date was parsed in. Don't forget that, bestie. ๐Ÿซถ


โœจ 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. So like, go off. ๐Ÿ’…


๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

Sullivan Beck (https://github.com/SBECK-github/)


That's the whole page, bestie! This was perl v5.42.3, dated 2026-09-01, from Date::Manip::DM6(3). Thanks for coming to my TED talk. Mwah! ๐Ÿ’–โœจ๐ŸŽ€๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from