On 2017/09/25 10:12 AM, David Wellman wrote:
Hi,
We're designing a new feature which will involve a lot of date/time
calculations which we intend to do within the SQLite engine//....
The question has come up as to how we should store date/time values in our
tables? Basically how should we define our date/time columns?
A short summary of considerations for that decision:
There are three standard date-time storage options (there are others
too, but these are the defacto go-to for most systems, all of which
SQLite handles well):
A - Storing an INTEGER Unix timestamp (Seconds or Milliseconds since a
base UTC date) or Julian day value,
B - Storing FLOAT/REAL where the Integer part describes the days since a
base date, typically 1/1/1900 or 1/1/1970, depending on who you roll
with and
C - Storing a string with a date or date and time, typically the
standard form is ISO8601 which looks like 'YYYY-MM-DDTHH:NN:SS.MSS
+ZZ:ZZ' with the T optionally being a space and the + could be + or - to
indicate offset (Zulu time) etc. Some parts are optional, there is a
good argument to not store Zulu time (offsets) but revert to UTC and let
the displaying app format the time to whatever time-frame the user
expects (much like Unix timestamps), so most actual stored dates end up
as simply 'YYYY-MM-DD HH:NN:SS' or even just 'YYYY-MM-DD' if not
interested in the time.
All of these have pro's and cons. Integer storage is usually most
efficient, but it takes some calculation to interpret, however SQLite is
very efficient at it, but if you want to do it in your own code, you
will need some standard functions to do so.
REAL/FLOAT is used by many systems (such as MS Excel) and it is a really
great storage method for doing time-intensive calculations and being
easy to understand by humans (well, a bit more-so than Unix stamps
anyway). Adding a day is as simple as adding 1 to the value (with the
Unix timestamp you have to add 86400), adding 12 hours (half a day) is
as easy as adding 0.5, etc. Subtracting 3 o'clock from 9 o'clock leaves
you with 0.25, which is a quarter of a day, so 6 hours exactly, and so on.
Strings take up some more space (though not that much actually) but has
the one significant advantage when trouble-shooting or debugging, that
the date is completely human readable as it is stored in the table, a
mere glance at the data will already tell you if the date is a factor in
whatever problem you are solving, whereas the other formats need a bit
of interpretation first (though very easy with a basic format statement
in the query). It has the disadvantage that, although SQLite provides
great and easy-to-use date-time adding/calculating functions, they do
take some more CPU cycles parsing the date string. (To be fair, I've
measured this at some point, and it was negligible, and even though it
was long ago, I doubt SQLite got worse at parsing dates.)
I always use ISO8601 strings storing UTC (non-offset) dates and times,
UNLESS data storage space is a big problem or date-time calculation is a
constant feature of the intended use of the table, then an Integer Unix
timestamp. If the date is simply stored and referenced in a normal way,
ISO date strings it is.
Note that these are my preferences when balancing data storage
considerations with ease of use and working/debugging efficiency, they
are by no means the "industry standard", if such a thing exists.
PS: If you do store ISO date strings, the suggested column TYPE in
SQLite terms is "NUMERIC" (not "TEXT"). At least that is what SQLite
itself relays DATE and DATETIME types to. I doubt it matters greatly,
but I use NUMERIC for any kind of date and it seems to work well, and if
I decide to change the date-time storage format later, it requires
merely an UPDATE query as opposed to a schema change.
Ref: Section 3.1.1 on this page:
http://www.sqlite.org/datatype3.html#affinity_name_examples
Cheers,
Ryan
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users