Day home Documentation
Day data representation
Low-level storage formats for inter-operability
Contents

32-bits and inter-operability

Days are easily stored as 32-bit integers but there may be situations where it is convenient to use other data representations. Typically a database may be configured with date-time column types so you would convert a Day into a SQL compatible string to store it, and of course the reverse. One important aspect of this is that as a Day contains more information than day, month, year we need to hi-jack the hours and minutes of such a storage method. This hack has been designed so that existing dates in the storage system can be read as well as the enhanced versions.

Days can inter-operate (obviously limited by what's possible by the storage medium) with Javascript Date, and Unix timestamps.

Therefore there are two main sections to this specification:

  1. How bits are used in the native 32-bit representation
  2. How Days can inter-operate either as fully qualified calendar days (D,M,Y all specified) and also be shoe-horned with into existing date-time storage fields

Introduction

Efficient storage of Days is important as is the ability to sort sensibly out-of-the-box. The native 32-bit encoding supports dates and intervals and is the preferred method of data storage and transmission.

Existing systems may require interfacing with Day and this can cause issues as they have no special values and don't support partial dates such as say 'May 2013'. For these we create or consume hacked versions which use the hours, minutes and seconds elements to give a reasonable coverage of important Day values. Sometimes we want to store and read these bits and in others ignore them. For example to put a 'End-of-time' value into a legacy database 'date-time' field for later retrieval we will need the bits, while with a 'date of last login' field they would be ignored.

In general Days should be inter-operable with existing date-time systems with minimal code changes.

All encodings should be lossless in the Day -> Encoding -> Day sequence.


For all new data storage use the 32 bit version
myUInt32var = myDay.To32Bits(); myDay = new DAYo(myUInt32var);

Native 32-bit integer

BitsSizeUsageNotes
31-293SignatureSee signature values below
281Sign0=BC/Negative.
1=AD/+ve
27-1612Year0...4095
15-124Month1=Jan,12=Dec 0 is legal
11-75Day of month1...31 0 is legal
6-43Not valid reasonSee error codes below
31Not used
21Monthly precisionDate : 1=month is valid
Interval : 1=to month precision
11Daily precisionDate : 1=fully specified
Interval : 1=to day precision
01Interval1=Interval 0=Date
Note that from an encoding point of view it is possible to have a signature of NV followed by Y,M,D values and a not-valid reason. There is a possible use for this where dates are being supplied in bulk by a process that can't reject the data outright.

Intervals use these bits differently.
BitsSizeUsageNotes
281Positive0=true
1=false
27-1315Years and days combinedPacked to maximize useful range combinations
12-112Split of years and days.4 possibilities
10-74Months0 to 11
6-43Precision or errorError 0..7 if NVIor precision 0..3

Signatures

Error codes

@@@ check width DAYu DFS_ constants
DecimalMnemonicDescription
0NVINot valid interval
1INTInterval
2NVNot valid (date)
3FLOFloating date
4NKNot known
5BOTBeginning of time
6CALCalendar date
7EOTEnd of time
DecimalDateInterval
0UnknownUnknown
1An unsuitable string or date was providedInput too short or long
2Too few or too many tokens
3Unable to interpret a non-numeric elementInitial sign missing
4Year element is missing, illegal or not 2 or 4 characters. Or month must be followed by year or dayUnknown unit
5Unable to parse (eg dmmyy needs an 0 at the front.) or can't tell day-month orderSign misplaced
6Unsuitable number element
7Function failure

Note that if these (unsigned) integers are sorted the most significant bits are the signatures followed by the year then month then day. This has the pleasant result that BoT comes before sorted dates which are followed by EoT. Furthermore 1982 comes before January 1982 which comes before 1st January 1982.

Strings

See below for inter-operation with existing databases etc.
We define a simple string format that can be used for JSON say, and is easy for other applications to read and write. Use this when the full functionality of dates is required. (If you just want fullly specified CALs then you could use YYYY-MM-DD.) This is a string with the elements separated by the tilde (~) character. signature~sign~year~month~day~error where (case insensitive)
signatureis one ofNVI,INT,NV,FLO,NK,BoT,Cal,EoTdefined inDAY.SIGNATURE_STRINGS
signis one of-ve,+ve,-,+defined inDAY.SIGN_STRINGS

Intervals

An interval always starts with a sign then one to three numbers with y, m or d suffix. The order doesn't matter. For example +1y 2m 3d is the same as +2m 3d 1y

Converting to/from other date formats

Common method

Warning: These functions are hacks where you're stuck with an existing data format.
Suppose you have to interface with an existing SQL database or one where other, less Day-savvy, applications will be dipping-in too. Clearly the bottom line is that you can only use fully specified dates. This clobbers the raison-d'etre of Day. But here is a ray of hope that could be used to spread a little happiness. The spare H:M:S parts of the timestamp are hi-jacked to provide the extra information a Day object can use.

Day signature D M Y H M S Comment
NVI 30 Dec 4096 BC 10 reason 0
INT 30 Dec 4096 BC 1 0 0 Not supported
NV 30 Dec 4096 BC 2 reason 0
FLO d m 0 3 mask 0 JS allows year zero!
NK 31 Dec 4096 BC 4 0 0
BOT 31 Dec 4096 BC 5 0 0
Earliest CAL 1 Jan 4095 BC 0 0 0 Fully specified CALs will always have 00:00:00 time
CAL d m y 0 mask 0
Latest CAL 31 Dec 4095 0 0 0
EOT 1 Jan 4096 7 0 0

A nice feature is that, provided you make sure no spurious hours creep in, other applications can do a simple switch on the hours for NV,NK,BoT and EoT which are great low-hanging fruit.

GOTCHA! You'll need to know what interfaces with this data and make sure it's documented, otherwise you could end up with spurious values propagating in all directions.

Conversion functions

For all new data storage use the 32 bit version
myInt32var = myDay.To32Bits(); myDay = new DAYo(myInt32var);
Javascript dates use
myJsDate = myDay.ToDate(); // if h,m,s in myJsDate are 0 then y,m,d are honest myDay = new DAYo(myJsDate);
Database strings will probably use
myDateTimeStr = myDay.ToYmdhms('YMDHMS'); myDay = new DAYo(myDateTimeStr, @@@DAYu.strTypeExtendedUnix);