=pod

=encoding utf8

=head1 NAME

Muldis::D::Ext::Temporal -
Muldis D extension for temporal data types and operators

=head1 VERSION

This document is Muldis::D::Ext::Temporal version 0.58.0.

=head1 PREFACE

This document is part of the Muldis D language specification, whose root
document is L<Muldis::D>; you should read that root document
before you read this one, which provides subservient details.

=head1 DESCRIPTION

Muldis D has a mandatory core set of system-defined (eternally available)
entities, which is referred to as the I<Muldis D core> or the I<core>; they
are the minimal entities that all Muldis D implementations need to provide;
they are mutually self-describing and are used to bootstrap the language;
any entities outside the core, called I<Muldis D extensions>, are
non-mandatory and are defined in terms of the core or each other, but the
reverse isn't true.

This current C<Temporal> document describes the system-defined I<Muldis D
Temporal Extension>, which consists of temporal data types and operators,
particularly calendar dates and intervals.  The bundled data types describe
common kinds of temporal artifacts according to modern calendars.  They can
represent a variety of precisions and epochs so that users can employ them
in a way that most accurately represents what they actually know about
their data.

The I<Muldis D Temporal Extension> is expressly not meant to be complete by
any means, as a solution for working with temporal data.  Rather it is
meant to be "good enough" for many common uses.  Moreover it isn't intended
to have a scope much greater than the temporal data handling abilities of
the ISO/IEC 9075 (SQL) standard and the Perl L<DateTime> module.  In many
situations, users may be better off ignoring this extension, and using
Muldis D's core facilities for user-defined types and routines, and code an
alternate temporal data solution that works best for them, building over
Muldis D's basic integer or such types, or alternately using third-party
Muldis D temporal extensions.  This current extension exists primarily to
ease the porting of SQL databases to Muldis D, and save users accustomed to
SQL's facilities and the Perl DateTime module's facilities from having to
frequently reinvent the wheel.  The details of this Muldis D extension are
typically just the same as those in ISO/IEC 9075 (SQL) section "4.6
Datetimes and intervals", but with some alterations.  As with SQL and
DateTime, dates and times are specified as YYYY.MM.DD.HH.MM.SS+ in the
proleptic Gregorian calendar, specifically the version with a year zero and
negative year numbers, either in the UTC time-zone or floating / no-zone.
Matters of "local time" or specifications of other time-zones or daylight
savings time are not supported for encoding into values, due partly to
various logical problems and complexity such as an inability to distinguish
between duplicated times of day around a daylight savings adjustment.  If
you want to work with "local time", you generally will have to convert to
UTC on input and from UTC on output with the I<Muldis D Temporal
Extension>; UTC is better for storage, local is maybe better for display.

Now the general practice of working with calendar-centric temporal data is
an imperfect process and can not be done with perfect mathematical
precision.  This is partly because our temporal data in general comes from
measurements of environmental cycles (such as rotations of the Earth,
revolutions of the Earth's moon around it, and revolutions of the Earth
around its sun), which not only are rounded approximations, but we also
know for a fact that the actual amount of time these events takes slowly
varies over time (such as that the rotation of the Earth is gradually
slowing as the moon gradually drifts away from it each year).  Also our
typical calendaring systems change over time, sometimes to deal with our
improved ability to measure the environmental cycles or compensate for
drift; witness for example a large part of the world's moving from the
Julian to the Gregorian calendar.  So the best we have to work with in
general will involve rounding, and sometimes a conceptually commutative or
associative sequence of operations on temporal data may not yield an
identical result from identical inputs when the operations are rearranged
into a conceptually equivalent but different form; a simple example being
adding or subtracting dates.  All the issues can be complicated.

This current document does not describe the polymorphic operators that all
types, or some types including core types, have defined over them; said
operators are defined once for all types in L<Muldis::D::Core>.

I<This documentation is pending.>

=head1 TYPE SUMMARY

Following are all the data types described in this document, arranged in a
type graph according to their proper sub|supertype relationships (but that
the first 3 just reappear from the core set to provide a similar context,
and aren't re-described here):

    sys.std.Core.Type.Universal

        sys.std.Core.Type.Empty

        sys.std.Core.Type.QScalar
            sys.std.Core.Type.Scalar

                # The following are all regular ordered scalar types.

                sys.std.Temporal.Type.UTCInstant
                    sys.std.Temporal.Type.UTCDateTime
                    sys.std.Temporal.Type.UTCDate
                    sys.std.Temporal.Type.UTCTime

                sys.std.Temporal.Type.FloatInstant
                    sys.std.Temporal.Type.FloatDateTime
                    sys.std.Temporal.Type.FloatDate
                    sys.std.Temporal.Type.FloatTime

                sys.std.Temporal.Type.Duration

                sys.std.Core.Type.Int

                    sys.std.Core.Type.NNInt

                        sys.std.Core.Type.PInt

                            # These are all finite positive integer types.

                            sys.std.Temporal.Type.PInt(12|31)

                        # These are all finite non-negative integer types.

                        sys.std.Temporal.Type.NNInt(23|59)

                sys.std.Rational.Type.Rat
                    sys.std.Rational.Type.NNRat

                        # These are all infinite non-neg rational types.

                        sys.std.Temporal.Type.NNRatLT62

I<This documentation is pending.>

=head1 SYSTEM-DEFINED TEMPORAL-CONCERNING DATA TYPES

These non-core data types are all ordered scalar types.

=head2 sys.std.Temporal.Type.PInt(12|31)

This is an enumeration data type.  C<PInt(12|31)> is a proper subtype of
C<PInt> where all member values are not greater than 12|31.  Its default
and minimum value is 1; its maximum value is 12|31.  The significance is
that in proleptic Gregorian dates, the (month|month-day) portion is a
positive integer not greater than 12|31.

=head2 sys.std.Temporal.Type.NNInt(23|59)

This is an enumeration data type.  C<NNInt(23|59)> is a proper subtype of
C<NNInt> where all member values are not greater than 23|59.  Its default
and minimum value is 0; its maximum value is 23|59.  The significance is
that in the time portion of proleptic Gregorian dates, the (hour|minute)
portion is a non-negative integer not greater than 23|59.

=head2 sys.std.Temporal.Type.NNRatLT62

This is an enumeration data type.  C<NNRatLT62> is a proper subtype of
C<NNRat> where all member values are less than 62.  Its default and minimum
value is 0; its maximum value is conceptually infinitessimally less than 62
and practically impossible.  The significance is that in the time portion
of proleptic Gregorian dates, the 'second' portion is a non-negative
rational less than 62.  The cardinality of this type is infinity; to define
a most-generalized finite C<NNRatLT62> subtype, you must specify the
greatest magnitude value denominator of its C<ratio> possrep, that is, its
maximum precision (that denominator is 10^9 if we're working to nanosecond
precision).

=head2 sys.std.Temporal.Type.UTCInstant

This is a structure data type.  A C<UTCInstant> is a single point in time,
or a periodic multiplicity of points in time, which is specified with
arbitrary precision using a set of unit quantities involving multiple
units, where the units do not generally have a fixed conversion rate with
each other.  A C<UTCInstant> is defined against the proleptic Gregorian
calendar and uses these 6 units: terrestrial year, month within year, day
within month, hour within day, minute within hour, second and possibly
fraction of a second within minute; the only fixed conversion rates are: 1
year is 12 months, 1 hour is 60 minutes.  A C<UTCInstant> is defined
against the UTC time-zone specifically, so you use it when you I<do know>
that the instant you are specifying was experienced in the UTC time-zone
with the specified unit values; if you are otherwise working according to
your local time-zone, you would be selecting your C<UTCInstant> values in
terms of a time-zone offset (and daylight-savings time offset if
applicable) from your local time.

A C<UTCInstant> has 1 system-defined possrep whose name is C<instant>,
which has 6 attributes: C<year> (a C<maybe_of.Int>), C<month> (a
C<maybe_of.PInt12>), C<day> (a C<maybe_of.PInt31>), C<hour> (a
C<maybe_of.NNInt23>), C<minute> (a C<maybe_of.NNInt59>), C<second> (a
C<maybe_of.NNRatLT62>).  For each attribute, that attribute should be a
C<Single> if a quanity in that unit is known, and it should be C<Nothing>
if there is no applicable or known quantity in that unit.  The C<year>
values greater than zero are CE, those less than zero are BCE.  The
C<month> value C<1> corresponds to the month of January, and C<12>
corresponds to the month of December.  The value of C<day> is further
restricted depending on the combined values of C<year> and C<month>, such
that all 3 together may only represent a valid date of the proleptic
Gregorian calendar (taking into account leap-days); so for example you
can't select April 31st or February 30th.  The value of C<second> is
further restricted as per C<day>, as leap-seconds are only valid on certain
days, and perhaps only when the hour-minute is 23-59.  These further
restrictions do not apply if any of the attributes needed to calculate
whether they apply are C<Nothing>.

The default value of C<UTCInstant> is exactly midnight at the start of
January 1st of the year 1 CE (which also happens to be the proleptic
Gregorian calendar's epoch); its minimum and maximum values are
conceptually infinities and practically impossible.  The cardinality of
this type is infinity; to define a most-generalized finite C<UTCInstant>
subtype, you must specify the earliest and latest dates it includes
(minimally, the earliest and latest C<year>), as well as the granularity of
the type as a fraction of a second (minimally, the largest value
denominator for C<second>).

The C<UTCInstant> type has a default ordering algorithm; for 2 distinct
C<UTCInstant> values, the earlier value is ordered before the later value.
To make full ordering of C<UTCInstant> values possible and deterministic
(though semi-meaningless) in the face of unknown/inapplicable attributes;
the algorithm works like this: 1. ordering is done numerically one
attribute at a time, from the largest units to the smallest; 2. for each
attribute, the C<Nothing> value will order before any C<Single> value.

=head2 sys.std.Temporal.Type.UTCDateTime

This is an enumeration data type.  A C<UTCDateTime> is a single specific
time on a specific date, with precision to arbitrary fractions of a second.
A C<UTCDateTime> is a proper subtype of C<UTCInstant> where all 6
attributes of its C<instant> possrep have C<Single> / known values.  A
C<UTCDateTime> adds 1 system-defined possrep whose name is C<datetime>,
which has 6 attributes: C<year> (an C<Int>), C<month> (a C<PInt12>), C<day>
(a C<PInt31>), C<hour> (a C<NNInt23>), C<minute> (a C<NNInt59>), C<second>
(a C<NNRatLT62>).  The default and minimum and maximum values are the same
as for C<UTCInstant>.

=head2 sys.std.Temporal.Type.UTCDate

This is an enumeration data type.  A C<UTCDate> is a single specific
terrestrial day, at no particular time of day.  A C<UTCDate> is a proper
subtype of C<UTCInstant> where the 3 attributes of its C<instant> possrep
named [C<year>, C<month>, C<day>] have C<Single> / known values, and the
other 3 C<instant> possrep attributes each have the C<Nothing> / unknown
value.  A C<UTCDate> adds 1 system-defined possrep whose name is C<date>,
which has 3 attributes: C<year> (an C<Int>), C<month> (a C<PInt12>), C<day>
(a C<PInt31>).  The default value of C<UTCDate> is January 1st of the year
1 CE; its minimum and maximum values are conceptually infinities and
practically impossible.  The cardinality of this type is infinity; to
define a most-generalized finite C<UTCDate> subtype, you must specify the
earliest and latest dates it includes (minimally, the earliest and latest
C<year>).

=head2 sys.std.Temporal.Type.UTCTime

This is an enumeration data type.  A C<UTCTime> is a single specific time
that isn't on any day in particular (or alternately that is repeating on
multiple days), with a precision to arbitrary fractions of a second; its
allowed range is between zero seconds (inclusive) and 1 terrestrial day
(exclusive).  A C<UTCTime> is a proper subtype of C<UTCInstant> where the 3
attributes of its C<instant> possrep named [C<hour>, C<minute>, C<second>]
have C<Single> / known values, and the other 3 C<instant> possrep
attributes each have the C<Nothing> / unknown value.  A C<UTCTime> adds 1
system-defined possrep whose name is C<time>, which has 3 attributes:
C<hour> (a C<NNInt23>), C<minute> (a C<NNInt59>), C<second> (a
C<NNRatLT62>).  The default and minimum value of C<UTCTime> is exactly
midnight at the start of its day (all of its C<time> possrep attributes are
zero-valued); its maximum value is conceptually infinitessimally less than
the midnight at the end of its day and practically impossible.  The
cardinality of this type is infinity; to define a most-generalized finite
C<UTCTime> subtype, you must specify the granularity of the type as a
fraction of a second (minimally, the largest value denominator for
C<second>).

=head2 sys.std.Temporal.Type.FloatInstant

This is a structure data type.  A C<FloatInstant> is exactly the same as
C<UTCInstant>, but that it is not defined against any specific time-zone,
but rather is floating; you use it when you I<do not know> in what
time-zone the specified date+time is supposed to refer to (it was just
I<somewhere>), or when that detail is not significant.  The C<FloatInstant>
type is disjoint from the C<UTCInstant> type, but all of its details save
its name and one aspect of its interpretation (representation, cardinality,
default values, ordering algorithm, etc) are identical.

=head2 sys.std.Temporal.Type.FloatDateTime

This is an enumeration data type.  C<FloatDateTime> is to C<UTCDateTime>
as C<FloatInstant> is to C<UTCInstant>.

=head2 sys.std.Temporal.Type.FloatDate

This is an enumeration data type.  C<FloatDate> is to C<UTCDate> as
C<FloatInstant> is to C<UTCInstant>.

=head2 sys.std.Temporal.Type.FloatTime

This is an enumeration data type.  C<FloatTime> is to C<UTCTime> as
C<FloatInstant> is to C<UTCInstant>.

=head2 sys.std.Temporal.Type.Duration

This is a structure data type.  A C<Duration> is a single amount of time,
which is specified with arbitrary precision using 6 quantities in the same
units as a C<UTCInstant> is structured with.  It is not fixed to any date
or time and is agnostic to the calendar, other than the interpretation of
units' size.  A C<Duration> is the result type of taking the difference
between two C<UTCInstant> values or between two C<FloatInstant> values, but
it is not defined in terms of said two values.

A C<Duration> has 1 system-defined possrep whose name is C<duration>, which
has 6 attributes: C<years>, C<months>, C<days>, C<hours>, C<minutes>, (all
5 each a C<maybe_of.Int>), C<seconds> (a C<maybe_of.Rat>).  Each attribute
value is C<Nothing> when it is unknown or not applicable, and a C<Single>
when it is known and applicable, as per a C<UTCInstant>.

The default value of C<Duration> is zero; its minimum and maximum values
are conceptually infinities and practically impossible.  The cardinality of
this type is infinity; to define a most-generalized finite C<Duration>
subtype, you must specify the maximum amount of time that its values may
be, plus the granularity of the type in fractions of a second; in other
words, you specify C<seconds> as per a C<Rat> and the other attributes as
per C<Int>.

The C<Duration> type has a default ordering algorithm which is structurally
the same as for C<UTCInstant>: 1. ordering is done numerically one
attribute at a time, from the largest units to the smallest; 2. for each
attribute, the C<Nothing> value will order before any C<Single> value.
However, because the unit values are unconstrained, this algorithm
will sort [0 months and 40 days] before [1 month and 0 days] even though
common sense says the second should be before the first.  So for ordering
to make sense, either in general leave all attributes C<Nothing> except one
(recommended), or otherwise be careful to just set compatible attribute
values.

=head1 FUNCTIONS FOR TEMPORAL MATH

These functions implement commonly used temporal math operations.

=head2 UTCInstant

=over

=item C<function sys.std.Temporal.UTCInstant.difference result Duration
params { minuend(UTCInstant), subtrahend(UTCInstant) }>

This function results in the duration-typed difference when its
instant-typed C<subtrahend> argument is subtracted from its instant-typed
C<minuend> argument.  The result is the amount of time between the 2
arguments, which may be positive or negative depending on which argument
was earlier.

=item C<function sys.std.Temporal.UTCInstant.abs_difference result Duration
params { topic(Duration), other(Duration) }>

This function results in the absolute difference between its 2 arguments.
The result is the amount of time between the 2 arguments, which is always
non-negative.

=item C<function sys.std.Temporal.UTCInstant.later result UTCInstant params
{ instant(Instant), duration(Duration) }>

This function results in the instant that is later than its C<instant>
argument by the amount of time in the C<duration> argument.

=item C<function sys.std.Temporal.UTCInstant.earlier result UTCInstant
params { instant(Instant), duration(Duration) }>

This function results in the instant that is earlier than its C<instant>
argument by the amount of time in the C<duration> argument.

=back

=head2 FloatInstant

=over

=item C<function sys.std.Temporal.FloatInstant.difference result Duration
params { minuend(FloatInstant), subtrahend(FloatInstant) }>

This function results in the duration-typed difference when its
instant-typed C<subtrahend> argument is subtracted from its instant-typed
C<minuend> argument.  The result is the amount of time between the 2
arguments, which may be positive or negative depending on which argument
was earlier.

=item C<function sys.std.Temporal.FloatInstant.abs_difference result
Duration params { topic(Duration), other(Duration) }>

This function results in the absolute difference between its 2 arguments.
The result is the amount of time between the 2 arguments, which is always
non-negative.

=item C<function sys.std.Temporal.FloatInstant.later result FloatInstant
params { instant(Instant), duration(Duration) }>

This function results in the instant that is later than its C<instant>
argument by the amount of time in the C<duration> argument.

=item C<function sys.std.Temporal.FloatInstant.earlier result FloatInstant
params { instant(Instant), duration(Duration) }>

This function results in the instant that is earlier than its C<instant>
argument by the amount of time in the C<duration> argument.

=back

=head2 Duration

Note that all inter-duration operators in general will just do the math on
each corresponding attribute individually and not normalize between
attributes.  This is subject to be revised in the future.

=over

=item C<function sys.std.Temporal.Duration.abs result Duration params {
topic(Duration) }>

This function results in the absolute value of its argument.

=item C<function sys.std.Temporal.Duration.sum result Duration params {
addends(bag_of.Duration) }>

This function results in the sum of the N element values of its argument;
it is a reduction operator that recursively takes each pair of input values
and adds (which is both commutative and associative) them together until
just one is left, which is the result.  If C<addends> has zero values, then
C<sum> results in the duration zero, which is the identity value for
addition.

=item C<function sys.std.Temporal.Duration.difference result Duration
params { minuend(Duration), subtrahend(Duration) }>

This function results in the difference when its C<subtrahend> argument is
subtracted from its C<minuend> argument.

=back

=head1 SYSTEM SERVICES FOR CURRENT DATES AND TIMES

These system service routines provide ways to get the current date or time
from the system.

=over

=item C<system_service sys.std.Temporal.UTCInstant.fetch_current_datetime
update { target(UTCDateTime) } read {}>

This system service routine will update the variable supplied as its
C<target> argument so that it holds the value of the current UTC date and
time (YMDHIS) as taken with the full precision that the implementation's
system clock or used time server supports.

=item C<system_service sys.std.Temporal.UTCInstant.fetch_current_date
update { target(UTCDate) } read {}>

This system service routine is the same as
C<sys.std.Temporal.UTCInstant.fetch_current_date> except that it only
produces an instant value with the date (YMD) attributes set.

=item C<system_service sys.std.Temporal.UTCInstant.fetch_current_time
update { target(UTCTime) } read {}>

This system service routine is the same as
C<sys.std.Temporal.UTCInstant.fetch_current_date> except that it only
produces an instant value with the time (HIS) attributes set; it still
retains the full precision.

=item C<system_service sys.std.Temporal.FloatInstant.fetch_current_datetime
update { target(FloatDateTime) } read {}>

This system service routine will update the variable supplied as its
C<target> argument so that it holds the value of the current floating date
and time (YMDHIS) as taken with the full precision that the
implementation's system clock or used time server supports.

=item C<system_service sys.std.Temporal.FloatInstant.fetch_current_date
update { target(FloatDate) } read {}>

This system service routine is the same as
C<sys.std.Temporal.FloatInstant.fetch_current_date> except that it only
produces an instant value with the date (YMD) attributes set.

=item C<system_service sys.std.Temporal.FloatInstant.fetch_current_time
update { target(FloatTime) } read {}>

This system service routine is the same as
C<sys.std.Temporal.FloatInstant.fetch_current_date> except that it only
produces an instant value with the time (HIS) attributes set; it still
retains the full precision.

=back

=head1 SEE ALSO

Go to L<Muldis::D> for the majority of distribution-internal
references, and L<Muldis::D::SeeAlso> for the majority of
distribution-external references.

=head1 AUTHOR

Darren Duncan (C<perl@DarrenDuncan.net>)

=head1 LICENSE AND COPYRIGHT

This file is part of the formal specification of the Muldis D language.

Muldis D is Copyright © 2002-2009, Darren Duncan.

See the LICENSE AND COPYRIGHT of L<Muldis::D> for details.

=head1 TRADEMARK POLICY

The TRADEMARK POLICY in L<Muldis::D> applies to this file too.

=head1 ACKNOWLEDGEMENTS

The ACKNOWLEDGEMENTS in L<Muldis::D> apply to this file too.

=cut
