NAME

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

VERSION

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

PREFACE

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

DESCRIPTION

Muldis D has a mandatory core set of system-defined (eternally available) entities, which is referred to as the Muldis D core or the 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 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 Temporal document describes the system-defined Muldis D Temporal Extension, which consists of temporal data types and operators, particularly calendar dates, times and intervals. The bundled data types describe common kinds of temporal artifacts according to modern calendars. They come in a variety of precisions and epochs so that users can pick one that most accurately represents what they actually know about their data.

The 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. 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 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, dates and times are specified as YYYY.MM.DD.HH.MM.SS.F+ in the Gregorian calendar, with optional time-zone offsets from the UTC zone.

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 Muldis::D::Core.

This documentation is pending.

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.Scalar

        # The following are all regular ordered scalar types.

        sys.std.Temporal.Type.DurationOf(Y|M|D|I|S|FS)
        sys.std.Temporal.Type.DateTo(Y|M|D|I|S|FS)
        sys.std.Temporal.Type.DateTo(I|S|FS)WithTZ
        sys.std.Temporal.Type.TimeTo(I|S|FS)
        sys.std.Temporal.Type.TimeTo(I|S|FS)WithTZ

        sys.std.Core.Type.Int

            sys.std.Core.Type.UInt

                sys.std.Core.Type.PInt

                    # These are all finite positive integer types.

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

                # These are all finite unsigned integer types.

                sys.std.Temporal.Type.UInt(23|59|62)

            # These are all infinite integer types.

            sys.std.Temporal.Type.NZInt

        sys.std.Rational.Type.Rat
            sys.std.Rational.Type.URat

                # These are all infinite unsigned rational types.

                sys.std.Temporal.Type.URatLT1

This documentation is pending.

SYSTEM-DEFINED TEMPORAL-CONCERNING DATA TYPES

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

sys.std.Temporal.Type.NZInt

A NZInt is a proper subtype of Int where all member values are not equal to zero. Its default value is 1. The significance is that in Gregorian dates, the year portion is an integer not equal to zero.

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

A PInt(12|31) is a proper subtype of 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 Gregorian dates, the (month|month-day) portion is a positive integer not greater than (12|31).

sys.std.Temporal.Type.UInt(23|59|62)

A UInt(23|59|62) is a proper subtype of UInt where all member values are not greater than (23|59|62). Its default and minimum value is 0; its maximum value is (23|59|62). The significance is that in the time portion of Gregorian dates, the (hour|minute|second) portion is an unsigned integer not greater than (23|59|62).

sys.std.Temporal.Type.URatLT1

A URatLT1 is a proper subtype of URat where all member values are less than one. Its default and minimum value is 0; its maximum value is conceptually infinitessimally less than one and practically impossible. The significance is that in Gregorian dates, the fractional-second portion is an unsigned integer less than one. The cardinality of this type is infinity; to define a most-generalized finite URatLT1 subtype, you must specify the greatest magnitude value denominator of its ratio possrep, that is, its maximum precision (that denominator is 10^9 if we're working to nanosecond precision).

sys.std.Temporal.Type.DurationOfFS

A DurationOfFS (duration of fractional seconds) is a single amount of time, with precision to arbitrary fractions of a second. It is not fixed to any date or time and is agnostic to the calendar. It is the result type of taking the difference between two DateToFS or two TimeToFS values. A DurationOfFS has 1 system-defined possrep whose name is the empty string, which has 1 attribute named fractional_seconds (a Rat). The default value of DurationOfFS 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 DurationOfFS subtype, you must specify the minimum and 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 as per a Rat. The DurationOfFS type has a default ordering algorithm which is conceptually the same as for Rat; for 2 distinct DurationOfFS values, the value closer to negative infinity is ordered before the value closer to positive infinity.

sys.std.Temporal.Type.DurationOf(Y|M|D|I|S)

A DurationOf(Y|M|D|I|S) (duration of years|months|days|minutes|seconds) is the same as DurationOfFS, but that its precision is appropriately less, going to the whole year|month|day|minute|second, and its only possrep's only attribute name is different, years|months|days|minutes|seconds, and the type of that attribute is instead an Int. While the cardinality of this type is infinity like DurationOfFS, DurationOf(Y|M|D|I|S) only needs specified minimum and maximum amounts of time to make it finite; unlike DurationOfFS, its granularity is already fixed.

sys.std.Temporal.Type.DateToFS

A DateToFS (date to the fractional second) is a single specific time on a specific date in the Gregorian calendar, with precision to arbitrary fractions of a second. It is a floating date which does not incorporate an explicit terrestrial time-zone offset duration, nor any concept of a daylight-savings time offset; you use it when you do not know the time-zone, or it is not significant, or you are simply working according to vanilla UTC all the time. A DateToFS has 1 system-defined possrep whose name is the empty string, which has 7 attributes: year (a NZInt), month (within year; a PInt12), day (within month; a PInt31), hour (within day; a UInt23), minute (within hour; a UInt59), second (within minute; a UInt62), fractional_second (within whole second; a URatLT1). There is no Gregorian year zero; the year values greater than zero are CE, those less than zero are BCE. The month value 1 corresponds to the month of January, and 12 corresponds to the month of December. The value of day is further restricted depending on the combined values of year and month, such that all 3 together may only represent a valid date of the Gregorian calendar (taking into account leap-days); so for example you can't select April 31st or February 30th. The value of second is further restricted as per day, as leap-seconds are only valid on certain days, and perhaps only when the hour-minute is 23-59. The default value of DateToFS is exactly midnight at the start of 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 DateToFS subtype, you must specify the earliest and latest dates it includes (minimally, the earliest and latest year), as well as the granularity of the type as a fraction of a second (minimally, the largest value denominator for fractional_second). The DateToFS type has a default ordering algorithm; for 2 distinct DateToFS values, the earlier value is ordered before the later value.

sys.std.Temporal.Type.DateTo(Y|M|D|I|S)

A DateTo(Y|M|D|I|S) (date to the whole year|month|day|minute|second) is the same as DateToFS, but that its precision is appropriately less, going to the whole year|month|day|minute|second, and its possrep has appropriately fewer attributes, keeping the range of attributes from the most significant down to the one specific to its granularity. While the cardinality of this type is infinity like DateToFS, DateTo(Y|M|D|I|S) only needs specified earliest and latest dates to make it finite; unlike DateToFS, its granularity is already fixed.

sys.std.Temporal.Type.DateToFSWithTZ

A DateToFSWithTZ (date to the fractional second with time-zone offset) is the same as DateToFS, but that it does incorporate an explicit terrestrial time-zone offset (relative to UTC), so you use it when you do know the time-zone and it is significant (which is usually), and also you want to account for the concept of a daylight-savings time offset. Note that it is common to still choose the DateToFSWithTZ type over DateToFS when all of the dates being represented have an offset of zero for simplicity; use what type works best for you. A DateToFSWithTZ has 1 system-defined possrep whose name is the empty string, which has 8 attributes; the first 7 are the same attributes as the only possrep of DateToFS has, and the 8th attribute is the same as the sole attribute of the sole possrep of DurationOfI is in meaning and type, but that its name is time_zone_offset_minutes. Note that while the offset can currently be any integer, that will probably be made more restrictive in the future; conceptually all the time-zone offsets are in the range -12 hours to 14 hours. The default value of DateToFSWithTZ is the same as that of DateToFS but that it has also the default time-zone offset of zero. Matters of cardinality and minimum/maximum are as per an appropriate combination of DateToFS and DurationOfI. The DateToFSWithTZ type has a default ordering algorithm; for 2 distinct DateToFSWithTZ values, the earlier value is ordered before the later value (when both are normalized to the same time-zone).

sys.std.Temporal.Type.DateTo(I|S)WithTZ

A DateTo(I|S)WithTZ (date to the whole minute|second with time-zone offset) is to DateToFSWithTZ as DateTo(I|S) is to DateToFS.

sys.std.Temporal.Type.TimeToFS

A TimeToFS (time to the fractional second) is a single specific time that isn't on any day in particular, with precision to arbitrary fractions of a second. It is the same as DateToFS but that its only possrep has only the least significant 4 attributes: hour, minute, second, fractional_second. The default and minimum value of TimeToFS is exactly midnight at the start of its day (all of its 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 TimeToFS subtype, you must specify the granularity of the type as a fraction of a second (minimally, the largest value denominator for fractional_second). The TimeToFS type has a default ordering algorithm; for 2 distinct TimeToFS values, the earlier value is ordered before the later value.

sys.std.Temporal.Type.TimeTo(I|S)

A TimeTo(I|S) (time to the whole minute|second) is the same as TimeToFS, but that its precision is appropriately less, going to the whole minute|second, and its possrep has appropriately fewer attributes, keeping the range of attributes from the most significant down to the one specific to its granularity. The cardinality of this type is 1440|up-to-90720 (24*60)|(24*60*63).

sys.std.Temporal.Type.TimeToFSWithTZ

A TimeToFSWithTZ (time to the fractional second with time-zone offset) is to TimeToFS as DateToFSWithTZ is to DateToFS.

sys.std.Temporal.Type.TimeTo(I|S)WithTZ

A TimeTo(I|S)WithTZ (time to the whole minute|second with time-zone offset) is to TimeToFSWithTZ as TimeTo(I|S) is to TimeToFS.

FUNCTIONS FOR INTER-DURATION MATH

These functions implement commonly used temporal math operations that just work with durations and not dates or times. For functions in a namespace named with a precision, their parameters and result type have that same precision only. They mirror basic integer or rational numeric functions but for taking and resulting in durations. Or actually, most numeric functions are not reflected here; if you want to use more, you can extract the duration's attribute, use the normal math ops, and then select a new duration with the result. Or a few more functions can be added here later.

function sys.std.Temporal.DurationOf(Y|M|D|I|S|FS).abs result DurationOf(Y|M|D|I|S|FS) params { topic(DurationOf(Y|M|D|I|S|FS)) }

This function results in the absolute value of its argument.

function sys.std.Temporal.DurationOf(Y|M|D|I|S|FS).sum result DurationOf(Y|M|D|I|S|FS) params { addends(bag_of.DurationOf(Y|M|D|I|S|FS)) }

This function results in the sum of the N same-root-typed 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 addends has zero values, then sum results in the duration zero, which is the identity value for addition.

function sys.std.Temporal.DurationOf(Y|M|D|I|S|FS).difference result DurationOf(Y|M|D|I|S|FS) params { minuend(DurationOf(Y|M|D|I|S|FS)), subtrahend(DurationOf(Y|M|D|I|S|FS)) }

This function results in the difference when its subtrahend argument is subtracted from its same-root-typed minuend argument.

FUNCTIONS FOR DATE AND TIME MATH

These functions implement commonly used temporal math operations that have date or time valued arguments. For functions in a namespace named with a precision, their parameters and result type have that same precision only.

DateTo(Y|M|D|I|S|FS)

function sys.std.Temporal.DateTo(Y|M|D|I|S|FS).difference result DurationOf(Y|M|D|I|S|FS) params { minuend(DateTo(Y|M|D|I|S|FS)), subtrahend(DateTo(Y|M|D|I|S|FS)) }

This function results in the duration-typed difference when its date-typed subtrahend argument is subtracted from its date-typed minuend argument. The result is the amount of time between the 2 arguments.

function sys.std.Temporal.DateTo(Y|M|D|I|S|FS).later result DateTo(Y|M|D|I|S|FS) params { date(DateTo(Y|M|D|I|S|FS)), duration(DurationOf(Y|M|D|I|S|FS)) }

This function results in the date that is later than its date argument by the amount of time in the duration argument.

function sys.std.Temporal.DateTo(Y|M|D|I|S|FS).earlier result DateTo(Y|M|D|I|S|FS) params { date(DateTo(Y|M|D|I|S|FS)), duration(DurationOf(Y|M|D|I|S|FS)) }

This function results in the date that is earlier than its date argument by the amount of time in the duration argument.

DateTo(I|S|FS)WithTZ

function sys.std.Temporal.DateTo(I|S|FS)WithTZ.difference result DurationOf(I|S|FS) params { minuend(DateTo(I|S|FS)WithTZ), subtrahend(DateTo(I|S|FS)WithTZ) }

This function results in the duration-typed difference when its date-typed subtrahend argument is subtracted from its date-typed minuend argument. The result is the amount of time between the 2 arguments. If the 2 arguments have the same time-zone offset, the rules for that time-zone apply; otherwise, they are both normalized to an offset of zero, and then the rules for that time-zone are applied.

function sys.std.Temporal.DateTo(I|S|FS)WithTZ.later result DateTo(I|S|FS) params { date(DateTo(I|S|FS)WithTZ), duration(DurationOf(I|S|FS)) }

This function results in the date that is later than its date argument by the amount of time in the duration argument. The result has the same time-zone as its date argument, and the rules for that time-zone apply.

function sys.std.Temporal.DateTo(I|S|FS)WithTZ.earlier result DateTo(I|S|FS) params { date(DateTo(I|S|FS)WithTZ), duration(DurationOf(I|S|FS)) }

This function results in the date that is earlier than its date argument by the amount of time in the duration argument. The result has the same time-zone as its date argument, and the rules for that time-zone apply.

TimeTo(I|S|FS)

function sys.std.Temporal.TimeTo(I|S|FS).difference result DurationOf(I|S|FS) params { minuend(TimeTo(I|S|FS)), subtrahend(TimeTo(I|S|FS)) }

This function results in the duration-typed difference when its time-typed subtrahend argument is subtracted from its time-typed minuend argument. The result is the amount of time between the 2 arguments. The 2 arguments are treated as being on the same day.

function sys.std.Temporal.TimeTo(I|S|FS).later result TimeTo(I|S|FS) params { time(TimeTo(I|S|FS)), duration(DurationOf(I|S|FS)) }

This function results in the time of day that is later than its time argument by the amount of time in the duration argument. If the added duration would take the time to midnight, it will wrap around.

function sys.std.Temporal.TimeTo(I|S|FS).earlier result TimeTo(I|S|FS) params { time(TimeTo(I|S|FS)), duration(DurationOf(I|S|FS)) }

This function results in the time of day that is earlier than its time argument by the amount of time in the duration argument. If the subtracted duration would take the time earlier than midnight, it will wrap around.

TimeTo(I|S|FS)WithTZ

function sys.std.Temporal.TimeTo(I|S|FS)WithTZ.difference result DurationOf(I|S|FS) params { minuend(TimeTo(I|S|FS)WithTZ), subtrahend(TimeTo(I|S|FS)WithTZ) }

This function is to sys.std.Temporal.TimeTo(I|S|FS).difference what sys.std.Temporal.DateTo(I|S|FS)WithTZ.difference is to sys.std.Temporal.DateTo(I|S|FS).difference.

function sys.std.Temporal.TimeTo(I|S|FS)WithTZ.later result TimeTo(I|S|FS) params { time(TimeTo(I|S|FS)WithTZ), duration(DurationOf(I|S|FS)) }

This function is to sys.std.Temporal.TimeTo(I|S|FS).later what sys.std.Temporal.DateTo(I|S|FS)WithTZ.later is to sys.std.Temporal.DateTo(I|S|FS).later.

function sys.std.Temporal.TimeTo(I|S|FS)WithTZ.earlier result TimeTo(I|S|FS) params { time(TimeTo(I|S|FS)WithTZ), duration(DurationOf(I|S|FS)) }

This function is to sys.std.Temporal.TimeTo(I|S|FS).earlier what sys.std.Temporal.DateTo(I|S|FS)WithTZ.earlier is to sys.std.Temporal.DateTo(I|S|FS).earlier.

SYSTEM SERVICES FOR CURRENT DATES AND TIMES

These system service routines provide ways to get the current date or time from the system. For routines in a namespace named with a precision, their parameters have that same precision only.

system_service sys.std.Temporal.DateTo(Y|M|D|I|S|FS).fetch_current_date_utc update { target(DateTo(Y|M|D|I|S|FS)) } read {}

This system service routine will update the variable supplied as its target argument so that it holds the value of the current utc date as taken with precision of the (whole year|month|day|minute|second)|(fractional second).

system_service sys.std.Temporal.DateTo(Y|M|D|I|S|FS).fetch_current_date_local update { target(DateTo(Y|M|D|I|S|FS)) } read {}

This system service routine will update the variable supplied as its target argument so that it holds the value of the current system-local date as taken with precision of the (whole year|month|day|minute|second)|(fractional second).

system_service sys.std.Temporal.DateTo(I|S|FS)WithTZ.fetch_current_date_utc update { target(DateTo(I|S|FS)WithTZ) } read {}

This system service routine will update the variable supplied as its target argument so that it holds the value of the current utc date as taken with precision of the (whole minute|second)|(fractional second).

system_service sys.std.Temporal.DateTo(I|S|FS)WithTZ.fetch_current_date_local update { target(DateTo(I|S|FS)WithTZ) } read {}

This system service routine will update the variable supplied as its target argument so that it holds the value of the current system-local date as taken with precision of the (whole minute|second)|(fractional second).

system_service sys.std.Temporal.TimeTo(I|S|FS).fetch_current_time_utc update { target(TimeTo(I|S|FS)) } read {}

This system service routine will update the variable supplied as its target argument so that it holds the value of the current utc time as taken with precision of the (whole minute|second)|(fractional second).

system_service sys.std.Temporal.TimeTo(I|S|FS).fetch_current_time_local update { target(TimeTo(I|S|FS)) } read {}

This system service routine will update the variable supplied as its target argument so that it holds the value of the current system-local time as taken with precision of the (whole minute|second)|(fractional second).

system_service sys.std.Temporal.TimeTo(I|S|FS)WithTZ.fetch_current_time_utc update { target(TimeTo(I|S|FS)WithTZ) } read {}

This system service routine will update the variable supplied as its target argument so that it holds the value of the current utc time as taken with precision of the (whole minute|second)|(fractional second).

system_service sys.std.Temporal.TimeTo(I|S|FS)WithTZ.fetch_current_time_local update { target(TimeTo(I|S|FS)WithTZ) } read {}

This system service routine will update the variable supplied as its target argument so that it holds the value of the current system-local time as taken with precision of the (whole minute|second)|(fractional second).

SEE ALSO

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

AUTHOR

Darren Duncan (perl@DarrenDuncan.net)

LICENSE AND COPYRIGHT

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

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

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

TRADEMARK POLICY

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

ACKNOWLEDGEMENTS

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