I’m storing two dates in the PostgreSQL database. First, is the data of visit of a webpage, and the second date is the date of last modification of the webpage(this is get as a long).
I have some doubts what is the best strategy to store these values.
I only need day/month/year and hour:seconds and this will only for statistical proposes.
So, some doubts:
- is best store as long and convert on recover of information or store in the data format above?
- is best set the date of visit on the software or in the insertion in the database?
- in Java, how are the best classes to handle dates?
Any strategy for storing date-and-time data in PostgreSQL should, IMO, rely on these two points:
Instantor aLocalDateTimedatatype.My recipe follows.
If you want to record the physical instant at when a particular event ocurred, (a true "timestamp" , typically some creation/modification/deletion event), then use:
Instant(Java 8 , or Jodatime).java.sql.TimestampTIMESTAMP WITH TIMEZONE(TIMESTAMPTZ)(Don’t let PostgreSQL peculiar datatypes
WITH TIMEZONE/WITHOUT TIMEZONEconfuse you: none of them actually stores a timezone)Some boilerplate code: the following assumes that
psis aPreparedStatement,rsaResultSetandtzUTCis a staticCalendarobject corresponding toUTCtimezone.Write
Instantto databaseTIMESTAMPTZ:Read
Instantfrom databaseTIMESTAMPTZ:This works safely if your PG type is
TIMESTAMPTZ(In that case, thecalendarUTChas no effect in that code ; but it’s always advisable to not depend on defaults timezones)."Safely" means that the result will not depend on server or database timezone, or timezones information: the operation is fully reversible, and whatever happens to timezones settings, you’ll always get the same "instant of time" you originally had on the Java side.
If, instead of a timestamp (an instant on the physical timeline), you are dealing with a "civil" local date-time (that is, the set of fields
{year-month-day hour:min:sec(:msecs)}), you’d use:LocalDateTime(Java 8 , or Jodatime).java.sql.TimestampTIMESTAMP WITHOUT TIMEZONE(TIMESTAMP)Read
LocalDateTimefrom databaseTIMESTAMP:Write
LocalDateTimeto databaseTIMESTAMP:Again, this strategy is safe and you can sleep peacefully: if you stored
2011-10-30 23:59:30, you’ll retrieve those precise fields (hour=23, minute=59… etc) always, no matter what – even if tomorrow the timezone of your Postgresql server (or client) changes, or your JVM or your OS timezone, or if your country modifies its DST rules, etc.Added: If you want (it seems a natural requirement) to store the full datetime specification (a
ZonedDatetime: the timestamp together with the timezone, which implicitly also includes the full civil datetime info – plus the timezone)… then I have bad news for you: PostgreSQL hasn’t a datatype for this (neither other databases, to my knowledge). You must devise your own storage, perhaps in a pair of fields: could be the two above types (highly redundant, though efficient for retrieval and calculation), or one of them plus the time offset (you lose the timezone info, some calculations become difficult, and some impossible), or one of them plus the timezone (as string; some calculations can be extremely costly).