Reputation: 2457
Is there a standard way to represent a date as a single integer? (I only need to store dates, not full timestamps.)
If it matters, the reason I want to do this is because I'm storing the dates in a SQLite database on Android and would like to store them as numbers so they can be compared/sorted efficiently to return results from queries.
Upvotes: 3
Views: 4051
Reputation: 263577
One good option might be YYYYMMDD
, for example encoding today (Jan 13, 2014) as the integer 20140113
.
Advantages:
<
, ==
, and >
;Disadvantages:
On the last point: The SQLite3 documentation says that SQLite3 has no specific storage types for dates and/or times. Instead, it recommends using one of:
"YYYY-MM-DD HH:MM:SS.SSS"
).all of which apparently can be processed using SQLite's built-in date and time functions.
The latter argues in favor of the solution in bdf's answer. Picking an arbitrary time within the specified day is admittedly problematic, but I suggest picking noon UTC is unlikely to cause too many problems as long as you're careful to use it consistently. (Noon UTC can be on a different day if your time zone offset is 12 hours or more, but that's not an issue for most of the world.)
Upvotes: 4
Reputation: 1966
An important detail to keep in mind are time zones. If e.g. your time falls in the gap between your time zone offset and GMT you might get unexpected results. So at first I propose we discuss date
as the one visible to the user which is usually the one of the local time zone.
So if we assume local time, and we want to make use of the Date
objects, there are 2 possible solutions, which I will present as JavaScript unit test style. First one is the one presented by Keith Thompson previously:
let date = new Date('1987-12-31T01:02:03')
let simpleDateInteger = (
date.getFullYear() * 10000 +
(date.getMonth() + 1) * 100 +
date.getDate()
)
expect(simpleDateInteger).toBe(19871231)
let fromSimpleDateInteger = new Date(
simpleDateInteger / 10000, // year
simpleDateInteger / 100 % 100 - 1, // month
simpleDateInteger % 100 // day
)
expect(fromSimpleDateInteger.toDateString()).toEqual(date.toDateString())
If you need more compact integers and each integer +1 representing the next day, i.e. a continuous representation you can go with this one:
let date = new Date('1987-12-31T00:01:02')
const DAY_IN_MILLISECONDS = 86400 * 1000
let timeZoneInMilliSeconds = date.getTimezoneOffset() * 60 * 1000
let continuousDateInteger = Math.floor(
(date.getTime() - timeZoneInMilliSeconds) / DAY_IN_MILLISECONDS
)
expect(continuousDateInteger).toBe(6573)
let fromContinuousDateInteger = new Date(
continuousDateInteger * DAY_IN_MILLISECONDS + timeZoneInMilliSeconds
)
expect(fromContinuousDateInteger.toDateString()).toEqual(date.toDateString())
Upvotes: 0
Reputation: 247
just set the time for every day to an arbitrary time of your choosing, such as 2 am.
Storing them as timestamps anyway might still be a good idea, since you'd have a lot more date formatting options.
Upvotes: 2