NAME

Time::Keeper::Date - a date with no time of day

VERSION

Version 0.11

SYNOPSIS

use Time::Keeper;

my $d = Time::Keeper::Date->new(year => 2026, month => 10, day => 15);
my $d = Time::Keeper::Date->today(zone => 'Europe/London');
my $d = Time::Keeper::Date->parse('2026-10-15');
my $d = $t->to_date;                      # from a Time::Keeper value

$d->day_of_week;                          # 4, Thursday
$d->plus(months => 1);                    # 2026-11-15
$d->next(day_of_week => 1);               # the Monday after
$d->format('EEEE d MMMM y');              # Thursday 15 October 2026
$d->at(hour => 9, zone => 'Europe/London');   # a Time::Keeper value
"$d";                                     # 2026-10-15

DESCRIPTION

A date with no time of day and no zone: a birthday, a due date, a day in a calendar. It is not a Time::Keeper value and does not pretend to be one: it has no hour, no epoch and no zone, a pattern letter that needs a time of day is an error rather than a fabricated 00, and it compares only with another date. What it shares with a value it shares exactly: the same calendar arithmetic (months first, then days, so $a + ($b - $a) is $b), the same CLDR names and formats in every locale, the same parsers, the same serialisation hooks.

A date in a locale carries that locale into its names and formats, as a value does; see "LOCALES" in Time::Keeper.

CONSTRUCTORS

new

my $d = Time::Keeper::Date->new(year => 2026, month => 10, day => 15);
my $d = Time::Keeper::Date->new(year => 2026, month => 10, day => 15, locale => 'fr');

The date given. month and day default to 1. A day the month does not have is an error. There are no time keys and no zone.

last_day_of_month

from_day_of_year

from_iso_week

Time::Keeper::Date->last_day_of_month(year => 2024, month => 2);   # 2024-02-29
Time::Keeper::Date->from_day_of_year(year => 2026, day_of_year => 288);
Time::Keeper::Date->from_iso_week(year => 2026, week => 42, day => 4);

As "new" in Time::Keeper's aliases, without a time: the last day of the month, the day of the year, the day of the ISO week (day 1 Monday to 7 Sunday, default Monday).

today

my $d = Time::Keeper::Date->today;
my $d = Time::Keeper::Date->today(zone => 'Asia/Tokyo');

Today's date in the zone, UTC by default; it reads the clock "TESTING" in Time::Keeper describes.

from_epoch_days

my $d = Time::Keeper::Date->from_epoch_days(20741);   # 2026-10-15

The date that many days after 1 January 1970; negative for before.

parse

strptime

parse_cldr

Time::Keeper::Date->parse('2026-10-15');
Time::Keeper::Date->parse('2026-W42-4');
Time::Keeper::Date->parse('2026-288');
Time::Keeper::Date->strptime('15/10/2026', '%d/%m/%Y');
Time::Keeper::Date->parse_cldr('15 octobre 2026', 'd MMMM y', locale => 'fr');

As Time::Keeper's, but giving a date. parse reads the ISO 8601 date forms, calendar, week and ordinal, extended and basic, and refuses text that names a time of day, an offset or a zone: a date holds none of them. A month alone is its first day and a week alone its Monday. Under a pattern, the pattern says what the text holds and the date keeps the date: a %H in a strptime pattern is read and dropped. Each takes locale.

try_new

try_parse

try_strptime

try_parse_cldr

As the method without try_, but undef where it would die, with $@ left as it was.

ACCESSORS

year

month

day

day_of_week

day_of_year

quarter

day_of_quarter

week

week_year

week_of_month

is_leap_year

days_in_month

days_in_year

days_in_quarter

is_weekend

is_weekday

As "ACCESSORS" in Time::Keeper; week and week_year take locale => 1 for the locale's weeks.

epoch_days

Days since 1 January 1970, negative before it; the inverse of "from_epoch_days".

locale

The locale's code.

month_name

month_abbr

day_name

day_abbr

era_name

era_abbr

quarter_name

quarter_abbr

The locale's names, as "month_name" in Time::Keeper and the rest.

NEW DATES FROM OLD

with

$d->with(day => 1);
$d->with(day => 'last');
$d->with(day_of_year => 60);
$d->with(week => 42);            # keeps the day of the week
$d->with(day_of_week => 3);      # the Wednesday of the same ISO week

As "with" in Time::Keeper, for the date's parts.

in_locale

The same date in another locale.

to_year_month

to_month_day

$d->to_year_month;    # a Time::Keeper::YearMonth, 2026-10
$d->to_month_day;     # a Time::Keeper::MonthDay, --10-15

at

my $t = $d->at(hour => 9, minute => 30, zone => 'Europe/London');
my $t = $d->at($time_of_day, zone => 'Europe/London', gap => 'forward');
my $t = $d->at(zone => 'America/Sao_Paulo');    # midnight, or the first moment after it

The Time::Keeper value at that time of day on this date in the zone (UTC by default), with the date's locale. The time is given by its parts, or as a Time::Keeper::Time first. gap and overlap as for "new" in Time::Keeper; with no time given, a midnight the clocks skipped gives the first moment that happened, as "today" in Time::Keeper does.

ARITHMETIC

plus

minus

$d->plus(months => 1);
$d->plus(years => 1, months => 2, weeks => 3, days => 4);
$d->plus(months => 1, end_of_month => 'limit');
$d->plus($duration);
$d->minus($other_date);          # a duration

Years, months, weeks and days, by name or as a Time::Keeper::Duration, with end_of_month as "plus" in Time::Keeper takes it. Hours and anything smaller are an error: a date has no clock to add them to. minus with another date gives the duration from it to this one, months then days ("ARITHMETIC" in Time::Keeper). The operators + and - do the same.

delta_days

delta_md

The duration between two dates, in days alone, or in months and days; never negative.

truncate

round

end_of

$d->truncate(to => 'month');                      # the first
$d->truncate(to => 'week', week_start => 'locale');
$d->end_of(to => 'year');                         # 31 December
$d->round(to => 'month', mode => 'floor');

To a year, quarter, month or week, as "truncate" in Time::Keeper; end_of gives the period's last day.

next

previous

nth_in_month

last_in_month

$d->next(day_of_week => 1);
$d->next(day_of_week => 1, or_same => 1);
$d->nth_in_month(day_of_week => 4, n => 3);
$d->last_in_month(day_of_week => 7);

As "next" in Time::Keeper and the rest, without gap and overlap.

COMPARING AND PRINTING

compare

Time::Keeper::Date->compare($a, $b);   # -1, 0 or 1

The operators <=>, ==, < and so on do the same. A date compares only with another date; a Time::Keeper value or a year and month beside it is an error.

iso8601

TO_JSON

2026-10-15; years outside 0000 to 9999 with a sign and six digits. "$d" is the same.

ymd

mdy

dmy

date

As "ymd" in Time::Keeper; date is ymd with hyphens.

FORMATTING

strftime

format

format_date

format_skeleton

$d->format('EEEE d MMMM y');
$d->strftime('%A %-d %B %Y');
$d->format_date('full');
$d->format_skeleton('yMMMd');

As Time::Keeper's, for the date's letters. A letter that needs a time of day or a zone (H, a, z, %T, %c, %s and their kin) is an error naming it, not a fabricated value; "at" in Time::Keeper gives a value when a time is wanted.

SERIALISATION

STORABLE_freeze

STORABLE_thaw

FREEZE

THAW

Storable's and the Types::Serialiser protocol's hooks, as "SERIALISATION" in Time::Keeper: the frozen text carries the kind, so a frozen date thaws only as a date.

utc_rd_values

The Rata Die day and zero seconds, for DateTime's from_object.

SEE ALSO

Time::Keeper, Time::Keeper::YearMonth, Time::Keeper::MonthDay.

AUTHOR

LNATION, <email at lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)