=begin pod

=head1 NAME

DateTime::strftime - provide strftime() formatting for DateTime objects

=head1 SYNOPSIS

=begin code :lang<raku>
use DateTime::strftime;

say strftime(DateTime.now, '%c');  # default": EN
# Sun Jan 19 13:19:02 +0100 2025

say strftime(DateTime.now, '%c', "NL");
# zon 19 jan 13:19:02 +0100 2025

say strftime(DateTime.now, ':rfc2822:')
# Wed, 05 Aug 2026 18:03:10 +0200
=end code

=head1 DESCRIPTION

The C<DateTime::strftime> distribution provides a C<strftime>
subroutine that takes a C<DateTime> object, a
L<C<strftime>|https://linux.die.net/man/3/strftime> format string (or
its C<:text:> equivalent), and an optional locale indicator (which
defaults to the dynamic variable C<$*LOCALE-DATES> or C<"EN">).

It returns the representation of the C<DateTime> object according
to that format and locale.

=head1 FORMAT SPECIFICATION

The supported formats are a (large) subset of C<strftime>. The C<E>
and C<O> modifiers are B<not> supported.

Since the C<strftime> format codes are rather cryptic (although very
widely in use), one can also use an alternate C<:text:> format.  So
instead of the rather cryptic C<"%c">, one can also use C<":datetime:">.

=begin table

| Code | :text:      | Value
|------|-------------+------
| %a   | wkdname     | abbreviated weekday name
| %A   | weekdayname | full weekday name
| %b   | mnthname    | abbreviated month name
| %B   | monthname   | full month name
| %c   | datetime    | preferred date/time representation
| %C   | century     | century number (year div 100)
| %d   | 0day        | day of month ("01" .. "31")
| %D   | usadate     | short for: %m/%d/%y
| %e   | day         | day of month (" 1" .. "31")
| %f   |             | same as %M
| %F   | isodate     | short for: %Y/%m/%d
| %g   | weekYY      | YY of this week ("00" .. "99")
| %G   | weekYYYY    | full year of this week
| %h   |             | same as %b
| %H   | 0hour       | 24-hour hour ("00" .. "23")
| %I   | 0amhour     | 12-hour hour ("01" .. "12")
| %j   | yearday     | day of the year ("001" .. "366")
| %k   | hour        | 24-hour hour (" 1" .. "23")
| %l   | amhour      | 12-hour hour (" 1" .. "12")
| %L   |             | same as %Y
| %m   | month       | month ("01" .. "12")
| %M   | minute      | minute ("00" .. "59")
| %n   | newline     | "\n"
| %p   | AMPM        | "AM" \| "PM"
| %P   | ampm        | "am" \| "pm"
| %r   | amtime      | short for: %I:%M:%S %p
| %R   | HHMM        | short for: %H:%M
| %s   | epoch       | seconds since epoch (midnight 1970-01-01 UTC)
| %S   | second      | second ("00" .. "59")
| %t   | tab         | "\t"
| %T   | HHMMSS      | short for: %H:%M:%S
| %u   | weekday     | weekday (1 .. 7)
| %U   | weekSun     | week number (first Sunday) ("00" .. "53")
| %v   | DD-MON-YYYY | short for: %e-%b-%Y
| %V   | weekISO     | week number (ISO 8601) ("00" .. "53")
| %w   | 0weekday    | weekday (0 .. 6)
| %W   | weekMon     | week number (first Monday) ("00" .. "53")
| %x   | date        | preferred date representation
| %X   | time        | preferred time representation
| %y   | YY          | year without century ("00" .. "99")
| %Y   | year        | year (yyyy)
| %z   | tzoffset    | numeric timezone (±HHMM)
| %Z   | timezone    | timezone (no name: %z)
| %2   | rfc2822     | short for: %a, %d %b %Y %T %z
| %+   | unixdate    | short for: %a %b %e %T %Z %Y
| %%   | percent     | "%"

=end table

Please note that one probably shouldn't use the C<%g> and C<%y> formats
for anything that is persistent.  Data and programs stay around longer
then anybody expects, and we don't want another
L<Y2K|https://en.wikipedia.org/wiki/Year_2000_problem> problem, especially
in a 100-year programming language!

=head1 DEFAULT LOCALIZATION

=begin code :lang<raku>
my $*LOCALE-DATES = "NL";
say strftime($dt, ':weekdayname:');        # zondag
say strftime($dt, ':weekdayname:', "EN");  # Sunday
=end code

The C<$*LOCALE-DATES> dynamic variable can be set with the string of
the desired localization, or with an instantiated C<Locale::Dates> object.
It will then affect any call to C<strftime> that does B<not> have an
explicit localization specified.

=head1 LEXICAL REFINEMENT

=begin code :lang<raku>
use DateTime::strftime :refine;

say DateTime.now.strftime('%c');  # default": EN
# Sun Jan 19 13:19:02 +0100 2025

say DateTime.now.strftime(':datetime:', "NL");
# zon 19 jan 13:19:02 +0100 2025
=end code

You can also use C<DateTime::strftime> with the C<:refine> parameter.  This
will add a C<strftime> method to the C<DateTime> class in the lexical scope
in which the C<use> statement is located.  This allows one to not to have
to change existing code using the C<DateTime> class, while still having the
added functionality of a C<DateTime.strftime> method.

=head1 OTHER SOFTWARE

See also Jean Forget's
L<C<Date::Calendar::Strftime>|https://raku.land/zef:jforget/Date::Calendar::Strftime> and
L<C<Date::Calendar::Gregorian>|https://raku.land/zef:jforget/Date::Calendar::Gregorian>.

=head1 AUTHOR

Elizabeth Mattijsen <liz@raku.rocks>

Source can be located at: https://codeberg.org/lizmat/DateTime-strftime .
Comments and Pull Requests are welcome.

If you like this module, or what I'm doing more generally, committing to a
L<small sponsorship|https://github.com/sponsors/lizmat/>  would mean a great
deal to me!

=head1 COPYRIGHT AND LICENSE

Copyright 2025, 2026 Elizabeth Mattijsen

If you like this module, or what I'm doing more generally, committing to a
L<small sponsorship|https://github.com/sponsors/lizmat/>  would mean a great
deal to me!

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.

=end pod

# vim: expandtab shiftwidth=4
