Year, month and day or year and month or just a year | |
We simply don't know. (Not the same thing as | )|
We've found some logical error. (Not the same thing as | )|
We don't have data going back beyond a certain point | |
Ongoing. A very common pattern in real-world applications | |
A month or a month and a day. Start of tax years for example | |
Numeric values of days, months and years used when comparing or shifting days | |
Something went wrong with calculations |
Abstract date |
Abstract meaningsThe exact meanings of these values depends on the application. The systems developer has to know what these are.Beginning of time, End of time or Not known. Day has well defined rules for how to process these in various contexts. |
Calendar date | This is 'a date that might appear on a calendar'.
|
Floating date | This applies to days with unspecified 'more significant' components. ie.
|
Fully specified date | A calendar date where the three elements, year, month and day are defined and real. If it is 'one square' of the calendar on your wall then it's fully specified. |
Interval |
A DAYi object may be used to explicitly represent a time period expressed as ±,Y,M,D.
|
Julian date | The number of days elapsed since January 1st 4713 BC. For our purposes a serial number for days which always 'counts one' every 24 hours. This only applies to fully specified dates, but where this holds we can do exact date arithmetic.2. |
Period |
WarningDo not get the terminology of Periods mixed up with Intervals. An Interval is a particular type of Day object. A Period is a lack of Precision.A date never specifies a moment in time. The least span of time it covers is 24 hours. The Period of a date is the full range of possible dates that it might cover. For example "May 2007" covers a Period from "1st May 2007" to "31st May 2007" inclusive. |
Precision | Analogous to numerical precision when dates are specified as Y-M-D with Y being the most and D being least significant. Part of the power of Day is being able to deal with imprecise values. |
Signature | A top-level indicator of the type of value contained in a day encoding. |
DAY.version | String Telling the code build date and time. Version numbers are not used. |
DAY.iNV | Integer Occasionally a function that returns an integer will want to return an alarm rather than throw an exception. Js value happens to be -9999999 |
DAY.NVI | 0 Invalid interval |
DAY.INT | 1 Interval |
DAY.NV | 2 Not a date value |
DAY.FLO | 3 Floating date |
DAY.NK | 4 Date not known |
DAY.BoT | 5 Beginning of time Or such an interpretation as 'before we started counting' or 'some time ago' |
DAY.Cal | 6 Calendar day |
DAY.EoT | 7 End of time Or such an interpretation as 'not yet' |
DAY.UNIX_NV | Integer 13 Dec 1901 02:00:00 This value is without a reason code. (Which would be in minutes) -2147551200 |
DAY.UNIX_NK | Integer 13 Dec 1901 04:00:00 -2147544000 |
DAY.UNIX_BOT | Integer 13 Dec 1901 05:00:00 -2147540400 |
DAY.UNIX_EOT | Integer 18 Jan 2038 07:00:00 2147410800 |
DAY.appendix | string The actual file name being used. If no separate appendix found and using internal defaults then this will be en-gb.dax |
DAY.error | string Examine this if there's a problem loading an appendix. A null string indicates no problem found |
DAY.force2or4DigitYears | boolean If true then years must be in the form yy or yyyy @@@ Check actual implementation |
DAY.i18n | string relative path to directory where the appendices are located. @@@No trailing slash (to be allowed) |
DAY.intervalRegEx | string Regular expression that detects intervals as input Hack this if you don't want to use y, m and d |
DAY.yearLimit | integer Maximum allowable size of year + or - |
DAY.AllowDayOnlyIntervals | (optional boolean new value) Get/Set do we allow INTs to be created with more than 31 days eg +0y 0m 66d If not then the conversion factor 30.4375 (365.25/12) will be used. |
DAY.AllowExcessDaysInMonth | (optional boolean new value) Get/Set true if we allow silent coercing of slightly too many days in month to end of month For example is 31st September assumed to be the last day of September? If this is false then an input error will be raised. |
DAY.BCIndicator | (optional string new value) Get/set the string used for BC indication. Do not call with a null string unless you want the BC indicator to be eliminated! The get version would be called called as BCIndicator(). |
DAY.ImpliedYear | (optional integer) Get/Set numeric value of IMPLIED_YEAR Allowable inputs are 0,-1,-2 or a year > 999 |
DAY.InYearLimits | (Integer year to test), ↩ boolean Check to ensure the year given is within current limits. Only applies to INT and Cal. |
DAY.Initialise | There will always be an Initialise method which will set up the environment according to (a) some file or (b) some text. The JS implementation leaves getting a file (and any associated async issues) to the programmer and takes the text. |
DAY.IsDmyOrder | Boolean Get/set whether element order is D-M-Y (False if M-D-Y) |
DAY.Lookup | (string Key, integer number) ↩ string This is a low-level method to access the dictionary |
DAY.MonthName | (integer Number, integer Version) ↩ string Look up the month name for the given number. Version is 1 to 4 depending on the length required. |
DAY.SearchMonths | (string Input) ↩ integer Use the string supplied to see if it will match with any month names. If so then return 1 for Jnuary and so on. Return 0 for no match. This only matches when there is exactly one match even if that match is partial. For example J would fail as not being specific but Janua would succeed as although it is partial it can only refer to one month. |
DAY.SearchShortcuts | (string Input) ↩string See if input matches one of the shortcut formats. For example be would match with Beginning-of-time and would return BoT. If there's no match then return a null string. |
DAY.SetKeyValue | (string Key, string Value) This is a low-level method of setting some element of the environment. It is not persistent over sessions. |
DAY.TwoDigitFix | (optional number) Get/set TWO_DIGIT_FIX Allowed values are 0, 20 and 50 |
As well as the master constructor DAY(Initialiser,Instructions) there are some quickie constructors and a number of helper methods which deal with the awful details. These constructor-helpers are named DAY._Read... For example to create a 𝔻 from a Julian number you can call the constructor with var d = DAY(someJulianNumber,'J'); which will use ._ReadJulian() to do its dirty-work. If you want to reuse an existing 𝔻 object then you can call these methods directly, for example. d._FromArray(someArray); // warning no sanitizing
DAYu.MakeBOT | () Construct a 𝔻 for Beginning-of-time |
DAYu.MakeClone | (𝔻) This 𝔻 takes all the data from the argument What went wrong is blanked. |
DAYu.MakeEOT | () Construct a 𝔻 for End-of-time |
DAYu.MakeNK | () Construct a 𝔻 for Not-known |
DAYu.MakeNV | (number Code, optional string Description, optional 𝔻 Data)
Construct a 𝔻 for Not-valid
|
DAYu.MakeToday | () Construct a 𝔻 for today's date |
Initialiser type | Interpretation | ||||||||||||
Number |
| ||||||||||||
String |
| ||||||||||||
Js Date obj |
| ||||||||||||
𝔻 | Clone | ||||||||||||
Array | See FromArray() | ||||||||||||
Other | Unsuitable objects throwUnsuitable object Other types throwUnsuitable type |
try{
var d = new DAYo(someArgs,someInstruction);
if(!d.IsErrorFree()){ did everything go according to plan?
var errorMessage = DAYc.ExtendedErrorStr(d);
// do something userish with message
}
}catch(e){
// this is getting really weird
} |
As .ExtendedErrorString() returns a null string if there's no error there's a shortcut.
if(var emsg = DAYc.ExtendedErrorStr(d)){ // single = is correct
// do error handling etc. using emsg
|
𝔻._Read32Bits boolean |
(Unsigned integer)
See Data representation for details of 32-bit encoding. The resulting 𝔻 is faithful to the input. There is no validation in this routine but the master constructor will perform ._Sanitize(). If you want a guarenteed representation of the actual data bits then use the following instead of the master constructor. var d = new DAYo();
d._Read32Bits(someUnsignedInt);
|
||||||||||||||||||||||||||||||||||||||||||||||||
𝔻._ReadArray boolean |
(Array) The array is numerical of the form [Signature,Sign,Year,Month,Day,Error code] The Sign may be DAY.pos or DAY.neg, however any negative value for Year will take precidence over the Sign value. The resulting 𝔻 is faithful to the input, except the Year is non-negative. There is no validation in this routine. | ||||||||||||||||||||||||||||||||||||||||||||||||
𝔻._ReadDate boolean |
(Javascript Date object, optional boolean UseTimeBits)
Use a Javascript Date instance. Consider the simple case where you have an everyday Javascript Date you want to convert to a 𝔻. Simply write myDay = DAY.FromDate(myJsDate) Since Javascript dates all have actual day, month, year parts the result will be fully specified day representing a single calendar day. (The H:M:S parts will be lost.) So far so normal and simple, but there are edge cases where the year is 0 (Eeek! There is no year zero in the calendar as it goes straight from 1BC to 1AD.) or has a magnitude more than 4095. For soft-hearted reasons of indulgence we allow Javascript dates to use the H:M:S elements for vital storage. (Not recommended of course, but if you have to interface with a lagacy system then this may be an option.) The gnarly details of the encoding are here To force reading these H:M:S elements set UseTimeBits to true. |
||||||||||||||||||||||||||||||||||||||||||||||||
𝔻._ReadJulian boolean |
(number) Use a Julian day number. This will be a fully specified calendar date. There is no validation here. | ||||||||||||||||||||||||||||||||||||||||||||||||
𝔻._ReadString boolean |
(Inout string, Templates array of strings)
|
||||||||||||||||||||||||||||||||||||||||||||||||
𝔻._ReadText boolean |
(string String)
Try to interpret the text input.
This is quite involved as it requires conversion from userland terms to codeland, where they
then may be ambigious or partial and need configurable rules to arrive at a result.
Sections 5 and 8 of an appendix tweak the interpretation. Sections 1 and 3 and INPUT_HACKS in section 5 govern names of months. Day names are never used for input.
This is probably the most gnarly routine in Day. It tries to be super-flexible in itself, taking guidance from appendix settings. It's a pretty good idea to check 𝔻.IsErrorFree() straight afterwards. Remember you have the error code to userland translations in section 7 of the appendix, while 𝔻.GetWWWS() is a more detailed codeland message.
|
||||||||||||||||||||||||||||||||||||||||||||||||
𝔻._ReadTilde boolean |
(string tilde-representation)
Use our simple tilde format. (See Data Representation) [_ReadTilde] Unable to read tilde format" |
||||||||||||||||||||||||||||||||||||||||||||||||
𝔻._ReadTimestamp boolean |
(integer unixMilliseconds, optional boolean UseTimeBits)
|
||||||||||||||||||||||||||||||||||||||||||||||||
𝔻._ReadYMDHMS boolean |
(string, optional boolean UseTimeBits)
Use a string formatted as
YYYY-MM-DD with optional HH:MM:SS addition.
|
𝔻.AddDays ← 𝔻 |
(number) add (-ve for subtract) a given number of days from a specific CAL date.
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.AddMonths ← 𝔻 |
(number) Add ( -ve for subtract ) specified number of months.
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.AddYears ← 𝔻 |
() Calls 𝔻.AddMonths() | ||||||||||||||||||||||||||||||||||||||||||
DAYu.After ← boolean |
(𝔻 testDay) Compares the logical values of the dates. Returns true if THIS is DEFINITELY after testDay argument. Note there are many cases where this test doesn't make sense or where the data cannot possibly be interpreted. All of these will return false without any error being raised. Therefore it is up to the programmer to avoid propagating spurious FALSEs by suitably guarding before calling. | ||||||||||||||||||||||||||||||||||||||||||
DAYu.AsDays ← floating point number |
() Convert an interval into days. Result may be fractional and negative | ||||||||||||||||||||||||||||||||||||||||||
DAYu.Before ← boolean |
(𝔻 testDay) Compares the logical values of the dates. Returns true if THIS is DEFINITELY before testDay argument. Note there are many cases where this test doesn't make sense or where the data cannot possibly be interpreted. All of these will return false without any error being raised. Therefore it is up to the programmer to avoid propagating spurious FALSEs by suitably guarding before calling. | ||||||||||||||||||||||||||||||||||||||||||
𝔻.CalendarType ← integer |
() If this is a CAL then what type is it?
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.DateToString ← string |
(string Template)
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.Day ← integer |
() Returns the day value.
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.DayOfWeek ← integer |
() Day of the week
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.DumpStr ← string |
() Return string version of internal state for debugging. | ||||||||||||||||||||||||||||||||||||||||||
𝔻.FirstDay ← 𝔻 |
() Returns the first possible date covered by this 𝔻
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.FloatType ← integer |
() If this is a FLO then what type is it?
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.FractionOfMonth ← floating point |
() How far through month are we?
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.GetErrorCode ← integer |
() What is numerical value of the error code?
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.HasDay ← boolean |
() Return true if day component is specified | ||||||||||||||||||||||||||||||||||||||||||
𝔻.HasMonth ← boolean |
() Return true if month component is specified | ||||||||||||||||||||||||||||||||||||||||||
𝔻.HasYear ← boolean |
() Return true if year component is specified | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsBC ← boolean |
() Return true if the sign component is negative | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsBoT ← boolean |
() Test for BoT signature | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsCalendar ← boolean |
() Is this a CAL of the form Y or YM or YMD | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsEoT ← boolean |
() Test for EoT signature | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsErrorFree ← boolean |
() Return true if there is no error set | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsFloating ← boolean |
() Test for FLO signature | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsGiven ← boolean |
() This tests for a workable date. ie NK, BoT, CAL or EoT. | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsGoodCalendar ← boolean |
(boolean MonthRequired, boolean DayRequired) Is it error-free and a calendar day with specified precision? | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsKnown ← boolean |
() This tests for a known date. ie BoT, CAL or EoT. | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsNotKnown ← boolean |
() Test for NK signature. | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsRealPeriod ← boolean |
() Tests for a valid CAL which could be Y or YM. ie. Day component is missing | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsSameValue ← boolean |
(𝔻 AnotherDay, boolean StrictFlag)
Do the internal values (signature, sign, y, m, d) match?
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.IsSpecific ← boolean |
() Is this a Cal that referrs to a specified day. ie. Day, month and year components are all specified | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsToday ← boolean |
() Return true if this is today. | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsValid ← boolean |
()?????????????????????????????? | ||||||||||||||||||||||||||||||||||||||||||
𝔻.IsValidDate ← boolean |
()????????????????????????????? | ||||||||||||||||||||||||||||||||||||||||||
𝔻.Julian ← integer |
() Return Julian day number
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.LastDay ← 𝔻 |
() Returns the last possible date covered by this 𝔻
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.Middle ← 𝔻 |
() Returns the middle date covered by this 𝔻
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.Month ← integer |
() Returns month value
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.MonthsDifference ← floating point |
(𝔻) See class DAY.MonthsDifference() | ||||||||||||||||||||||||||||||||||||||||||
𝔻.Next ← 𝔻 |
() Return a 𝔻 which represents the 'next' in sequence. This may find the next day, month or year depending on the precision of the 𝔻 being examined.
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.Previous ← 𝔻 |
() See .Next() | ||||||||||||||||||||||||||||||||||||||||||
𝔻.Signature ← integer |
() Returns signature
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.SortsBefore ← boolean; |
(𝔻) Does the subject 𝔻 sort before the argument?
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.To32Bits ← unsigned integer |
()Returns an unsigned 32-bit number
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.ToDate ← Javascript Date |
() See 𝔻.ToYmdhms() | ||||||||||||||||||||||||||||||||||||||||||
𝔻.ToString ← string |
(optional string Template, optional boolean ExtendedErrorCode) General routine
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.ToTilde ← string |
(optional boolean NumericFlag) Return easy to read string that is part of a standard
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.ToYmdhms ← varies |
(string ResultType) Lossless encoding into a variety of types depending on ResultType.
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.Year ← signed integer |
() Returns year value
|
||||||||||||||||||||||||||||||||||||||||||
𝔻.YearsDifference ← floating point |
(𝔻) See class method DAY.YearsDifference() |
DAYu. ← array |
(number dayCount)
DayCount is a number of days (Not necessarily an integer)
Return an array of [Y,M,D] after applying the necessary conversions
|
|||||||||||||||
DAYu.DayOfMonthToFraction ← number |
(number of days) How far through the month is this d/m/y?
|
|||||||||||||||
DAYu.DaysDifference ← number |
(𝔻 aDay1, 𝔻 aDay2) Number of days difference between aDay1 and aDay2.
|
|||||||||||||||
DAYu.DaysInGivenMonth ← integer |
(integer Month, optional integer Year) How many days in given month?
|
|||||||||||||||
DAYu.EarliestFinish ← 𝔻 |
(array of 𝔻s, optional boolean IgnoreUnsuitable)
What is the earliest finish of these dates? Only CALs are suitable values for the array.
|
|||||||||||||||
DAYu.EarliestStart ← 𝔻 |
(array of 𝔻s, optional boolean IgnoreUnsuitable)
What is the earliest possible start of these dates? Only CALs are suitable values for the array.
|
|||||||||||||||
DAYu.FractionToDayOfMonth ← integer |
(number Year, number Month, number Fraction)
Given a decimal between 0 and 1 what is the equivalent day.
|
|||||||||||||||
DAYu.GetDefaultYear ← integer |
() return the default year.
|
|||||||||||||||
DAYu.IsLeapYear ← boolean |
(integer Year) Return true if the argument is a leap year. | |||||||||||||||
DAYu.JulianToYMD ← array |
(integer JulianDay) Split Julian day number into array of [Y,M,D]
|
|||||||||||||||
DAYu.LatestFinish ← 𝔻 |
(array of 𝔻s, optional boolean IgnoreUnsuitable)
What is the latest possible finish of these dates? Only CALs are suitable values for the array.
|
|||||||||||||||
DAYu.LatestStart ← 𝔻 |
(array of 𝔻s, optional boolean IgnoreUnsuitable)
What is the latest possible start of these dates? Only CALs are suitable values for the array.
|
|||||||||||||||
DAYu.MonthsDifference ← number |
(𝔻 Day1, 𝔻 Day2) calculate (or approximate if days are involved) the number of months difference.
|
|||||||||||||||
DAYu.SigStrToConst ← integer |
(string Signature) Convert a three character string into a signature constant
|
|||||||||||||||
DAYu.SigToStr ← string |
(string Signature, optional boolean NumericFlag) Signature code to three character string
|
|||||||||||||||
DAYu.SignStrToConst ← integer |
(string Sign)
|
|||||||||||||||
DAYu.SignToStr ← string |
(number Sign, optional boolean NumericFlag) Sign to three character string.
|
|||||||||||||||
DAYu.SortsBefore ← integer |
(𝔻 Day1, 𝔻 Day2)
Compare two DAYo objects. Return -1, 0 or +1;
|
|||||||||||||||
DAYu.YMDToJulian ← integer |
(number Year, number Month, number Day) Create Julian day number from Year, month and day
|
|||||||||||||||
DAYu.YearsDifference ← number |
(𝔻 Day1, 𝔻 Day2) 'Subtract' Day1 from Day2
|
|||||||||||||||
DAYu. ← |
()
|
The heart of an 𝕀 is a , , and counts. That's fairly simple, but there's a key extra element of precision. For example +1y 1m 1d appears to be accurate to a day, but what about +1y 1m 0d? Is it just that we don't happen to have any days, or is it that the calculations we performend to generate the 𝕀 were only accurate to a month? Without a precision we're reduced to making assumptions that may not be true. How old is your cat is unlikely to be +7y 0m 0d accurate to a day or even a month. In the case of my cat, seven years is a guess.
We're also going to have to record in our 𝕀 oddity situations where we couldn't compute an interval. Think of the semantic difference between How long have you had your leg in plaster? and How long was your leg in plaster? DAY can answer both those questions but then we need to stick the answer carefully into an 𝕀 ... store... retrieve... and process sensibly. (Until the plaster comes off we don't have closure. Before that the answer is six days and counting)
We need to distinguish between an 𝕀 that has actual errors, typically as a result of illegal operations or malformed data, and one that is peculiar. Then we're hoing to have to feed some of that back into 𝔻 methods. All-in-all, hours of fun for a wet afternoon!
Initialiser | Notes |
string | This is a reliable way to specify intervals and have the precision automatically set as well. See .FromString() |
number <4096 | Small magnitude numbers are assumed to be days. |
number >4095 | Assumed to be an unsigned 32-bit integer.1 See .From32Bits() |
array | See .FromArray() |
DAYi | Make a copy |
DAYo | Extract from a 𝔻.2 See .ReadDAYo() |
undefined | Allowed but not very useful for the general applications programmer. |
DAYu.MakeINT ← 𝕀 |
(Years,Months,Days)
|
DAYu.SumIntervals ← 𝕀 |
(array of 𝕀s)
|
.signature | integer DAYu.INT or DAYu.NVI
|
.positive | boolean
|
.days | integer
|
.months | integer
|
.years | integer
|
.errorCode | integer 0..7
When something goes wrong (in the sense of strange data or combinations of inputs) you can look at this to get a rough idea why.
|
.precision | integer 0..3
Is the precision years, months or days.
|
𝕀.Add ← 𝕀 |
(one 𝕀 or an array of 𝕀s , boolean UseDurations) What could be simpler than adding two intervals? The intention is simple but the implementation is subject to all sorts of difficulties. For example add +1y to +1d. Is that the same as adding +1y 0m 0d to +1d. Nope! This is why you have to understand precision and relate that to your purpose.
If the optional boolean argument UseDurations is true then the addition algorithm is different. In Interval-world a duration is a number of days. This is fantastic except for the difficuly converting between days to months and years. Often this will be just the ticket.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
𝕀.@ ← @ |
()
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
𝕀.@ ← @ |
()
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
𝕀.@ ← @ |
()
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
𝕀.@ ← @ |
()
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
𝕀.@ ← @ |
()
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
𝕀.@ ← @ |
()
|
DAYu. ← array |
(number dayCount)
DayCount is a number of days (Not necessarily an integer)
Return an array of [Y,M,D] after applying the necessary conversions
|