DateTi...exible(3pm)

πŸ’– DateTime::Format::Flexible β€” okay bestie, let's talk ✨

No cap, this is the perl manpage for DateTime::Format::Flexible πŸ¦‹ β€” the module that just... flexibly parses strings and turns them into DateTime objects. Yeah. That's the whole thing. It's giving "let the computer figure it out" energy and we're obsessed πŸ’…


🌸 NAME 🌸

DateTime::Format::Flexible β€” DateTime::Format::Flexible β€” it flexibly parses strings and turns them into DateTime objects, fr fr πŸŽ€


✨ SYNOPSIS ✨

use DateTime::Format::Flexible;
my $dt = DateTime::Format::Flexible->parse_datetime(
    'January 8, 1999'
);
# $dt = a DateTime object set at 1999-01-08T00:00:00

Like. That's it. That's the whole vibe check βœ…


πŸ¦‹ DESCRIPTION πŸ¦‹

Okay so picture this: you've been forced to use a program that made you type the date in one specific way, and you're sitting there like "bestie. why can't the computer just figure out what date I wanted??" 😭

If that's you, this module is literally for you. πŸ’œ

DateTime::Format::Flexible attempts to take any string you give it and parse it into a DateTime object. Any. String. Iconic behaviour honestly πŸ‘‘


🌈 USAGE 🌈

Under the covers, this module uses DateTime::Format::Builder. Sneaky. Love that for it 🧚

πŸ’« parse_datetime

Hand it a string and it attempts to parse it and hand you back a DateTime object. 🫢

And if it cannot? It throws an exception. Not me getting dramatic πŸ’€

my $dt = DateTime::Format::Flexible->parse_datetime( $date );

my $dt = DateTime::Format::Flexible->parse_datetime(
    $date,
    strip    => [qr{\.\z}],                  # optional, remove a trailing period
    tz_map   => {EDT => 'America/New_York'}, # optional, map the EDT timezone to America/New_York
    lang     => ['es'],                      # optional, only parse using spanish
    european => 1,                           # optional, catch some cases of DD-MM-YY
);

  • base (optional) β€” does the exact same thing as the method base. It sets a base datetime for incomplete dates. Requires a valid DateTime object as an argument, no exceptions bestie πŸ’…

example:

my $base_dt = DateTime->new( year => 2005, month => 2, day => 1 );
my $dt = DateTime::Format::Flexible->parse_datetime(
   '18 Mar',
    base => $base_dt,
);
# $dt is now 2005-03-18T00:00:00
  • strip (optional) β€” removes a substring from the string you're trying to parse. You can pass multiple regexes in an arrayref, go off πŸ‘‘

example:

my $dt = DateTime::Format::Flexible->parse_datetime(
    '2011-04-26 00:00:00 (registry time)',
    strip => [qr{\(registry time\)\z}],
);
# $dt is now 2011-04-26T00:00:00

This is highkey helpful if you have a whole load of dates you want to normalize and you already know about some weird formatting beforehand. πŸ“

  • tz_map (optional) β€” maps a given timezone to another recognized timezone. Values are given as a hashref. πŸ—ΊοΈ

example:

my $dt = DateTime::Format::Flexible->parse_datetime(
    '25-Jun-2009 EDT',
    tz_map => {EDT => 'America/New_York'},
);
# $dt is now 2009-06-25T00:00:00 with a timezone of America/New_York

This is helpful if you have a load of dates carrying timezones that aren't recognized by DateTime::Timezone. The audacity of those timezones πŸ™ˆ

  • lang (optional) β€” specify which language map plugins to use. 🌍

When DateTime::Format::Flexible parses a date with a string in it, it will search for a way to convert that string to a number. By default it searches through all the language plugins looking for a match.

NOTE: as of 0.22, it will only do this search if it detects a string in the given date.

Setting lang lets you limit the scope of that search. Boundaries! We love to see it βœ‹

example:

my $dt = DateTime::Format::Flexible->parse_datetime(
    'Wed, Jun 10, 2009',
    lang => ['en'],
);
# $dt is now 2009-06-10T00:00:00

Currently supported languages are english (en), spanish (es) and german (de). Contributions, corrections, requests and examples are VERY welcome. πŸ’–

See the DateTime::Format::Flexible::lang::en, DateTime::Format::Flexible::lang::es, and DateTime::Format::Flexible::lang::de for examples of the plugins. πŸ‘€

  • european (optional) β€” if european is set to a true value, an attempt will be made to parse as a DD-MM-YYYY date instead of the default MM-DD-YYYY.
⚠️ There is a chance that this will not do the right thing due to ambiguity. Ambiguity is the villain of this story 😭

example:

my $dt = DateTime::Format::Flexible->parse_datetime(
    '16/06/2010' , european => 1,
);
# $dt is now 2010-06-16T00:00:00
  • MMYY (optional) β€” by default, this module parses 12/10 as December 10th of the current year (MM/DD). πŸ—“οΈ

If you want it to parse that as MM/YY instead, you can enable the MMYY option. Main character choice honestly ✨

example:

my $dt = DateTime::Format::Flexible->parse_datetime('12/10');
# $dt is now [current year]-12-10T00:00:00

my $dt = DateTime::Format::Flexible->parse_datetime(
    '12/10', MMYY => 1,
);
# $dt is now 2010-12-01T00:00:00

This is useful if you know you're going to be parsing a credit card expiration date. πŸ’³ periodt.


πŸŽ€ base πŸŽ€

gets/sets the base DateTime for incomplete dates. Requires a valid DateTime object as an argument when setting. This defaults to DateTime->now. ⏰

example:

DateTime::Format::Flexible->base( DateTime->new(
    year => 2009, month => 6, day => 22
));
my $dt = DateTime::Format::Flexible->parse_datetime( '23:59' );
# $dt is now 2009-06-22T23:59:00

πŸ’… build πŸ’…

an alias for parse_datetime. Same thing, different name, still slaying 🫢


🌟 Example formats 🌟

A small list of supported formats, bestie:

YYYYMMDDTHHMMSS
YYYYMMDDTHHMM
YYYYMMDDTHH
YYYYMMDD
YYYYMM
MM-DD-YYYY
MM-D-YYYY
MM-DD-YY
M-DD-YY
YYYY/DD/MM
YYYY/M/DD
YYYY/MM/D
M-D
MM-D
M-D-Y
Month D, YYYY
Mon D, YYYY
Mon D, YYYY HH:MM:SS
... thousands more

there are 9000+ variations that are detected correctly in the test files (see t/data/* for most of them) 😱. If you can think of any that I do not cover, please let me know. We're building this together fr fr 🀝


πŸ”₯ NOTES πŸ”₯

As of version 0.11 you will get a DateTime::Infinite::Future object if the passed in date is 'infinity', and a DateTime::Infinite::Past object if the passed in date is '-infinity'. πŸ‘€β™ΎοΈ

If you are expecting these types of strings, you might want to check for 'is_infinite()' from the object returned. No surprises please πŸ™…

example:

my $dt = DateTime::Format::Flexible->parse_datetime( 'infinity' );
if ( $dt->is_infinite )
{
     # you have a Infinite object.
}

πŸ’€ BUGS/LIMITATIONS πŸ’€

You cannot use a 1 or 2 digit year as the first field unless the year is > 31:

YY-MM-DD # not supported if YY is <= 31
Y-MM-DD  # not supported

It gets confused with MM-DD-YY. She's doing her best πŸ˜­πŸ’–


πŸ‘‘ AUTHOR πŸ‘‘

Tom Heady <cpan@punch.net> β€” legend behaviour honestly 🫢


Copyright 2007-2018 Tom Heady.

This program is free software; you can redistribute it and/or modify it under the terms of either:

  • the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or
  • the Artistic License.

🧚 SEE ALSO 🧚

DateTime::Format::Builder, DateTime::Timezone, DateTime::Format::Natural β€” go read them too, they're part of the family πŸ’œ


and that's the whole page bestie πŸ’– this was perl v5.40.0, dated 2025-01-11, and honestly? iconic. slay. parse those dates. periodt βœ¨πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from