How do you represent the date of birth in your Java model?

And wait, do not rush to answer "java.util.Date", consider the following scenario.

A Person object that has 2 fields: "birthday" and "nextMeeting", like java.util.Date. Now the birthday is stored in the database as a date type column (no time), for example. 01-10-1979, and nextMeeting as the datetime type for ex. 01-10-2010 20:00:00.

You pull it out of db, the "birthday" will be automatically set at midnight JDBC. Now you need to send this object to another JVM, using, for example, RMI or any other technology.

At the other end, the JVM has a time zone of -1h from the original JVM. This is where the problem begins. nextMeeting will become 01-10-2010 19:00:00, which is absolutely FINE and CORRECT from the point of view of the user, etc.

BUT the birthday will be 30-09-1979 23:00:00, which will be presented to the user as September 30, which is really not what we want, because, obviously, the birthday is something static and NOT time-dependent.

This type of column in db is selected correctly (date). This type of column is usually represented as java.util.Date. But in our case, this is the wrong java type to use.

So how would you imagine a birthday? Think that you need to manipulate this object in the user interface, for example, in the datepicker component, etc.

+6
java date
source share
6 answers

Use LocalDate from JodaTime and save the date of birth, not time.

+5
source share

Other answers use obsolete classes.

java.time

Both Joda-Time and the old java.util.Date/.Calendar classes were supplanted using the java.time framework built into Java 8 and later. Defined by JSR 310 . Extended in the ThreeTen-Extra project. Back-ported in Java 6 and 7 using the ThreeTen-BackPort project , which is completed for Android using the ThreeTenABP project.

LocalDate

A date value only with no time and no time zone can be represented by the LocalDate class. Such a class was not present in older time classes associated with earlier versions of Java. The old java.sql.Date class pretends to be date-only, but actually has a time inherited from java.util.Date (date value).

 LocalDate dateOfBirth = LocalDate.new( 1979 , 1 , 10 ); 

Without the time of day and time zone, the date of birth is inherently inaccurate for determining age. But in almost all precedents, we do not care. give or take part in the day close enough.

ZonedDateTime

For a meeting, we cannot be so licentious. We need a date, time and time zone. In java.time, this means the ZonedDateTime class. The time zone is a key element that is not in the script in the Question. Add a time zone and everything will be fine.

 ZoneId zoneIdMontreal = ZoneId.of( "America/Montreal" ); ZonedDateTime zdtMontreal = ZonedDateTime.of( 2010 , 1 , 10 , 20 , 0 , 0 , zoneIdMontreal ); 

Now transfer the objects to another computer. Both remain untouched, the same date value only for the date of birth (1979-01-10) and the same time for meeting in Montreal.

Time Zone Setting

You can then set up this appointment in a different time zone expected by the person using this other machine.

 ZoneId zoneIdParis = ZoneId.of( "Europe/Paris" ); ZonedDateTime zdtParis = zdtMontreal.withZone( zoneIdParis ); 

We have the same moment on the timeline, presented in two models, in two objects: zdtMontreal and zdtParis.

LocalDateTime

If your nextMeeting does not have a time zone or offset information from UTC, then think of it as a LocalDateTime object. It will be stored in the database as a type of type TIMESTAMP WITHOUT TIME ZONE .

Such values ​​do not represent a point in time. They represent only a number of possible points. To determine the actual moment, you must specify the context of a specific time zone.

To store future date values, such as a scheduled meeting, after more than a few weeks, doing this without a time zone may be appropriate. Politicians around the world have shown a tendency to change summer time frequently and, otherwise, redefine their time zones. And they often do this with a little warning, in just a few weeks of warning.

To determine the actual moment, for example, showing the schedule on the calendar, use the ZoneId time zone to get the ZonedDateTime .

ISO 8601

The java.time classes use standard ISO 8601 formats by default when parsing / generating text representations of date and time values. The ZonedDateTime class goes one step further, extending ISO 8601 to add the time zone name in square brackets.

If you serialize values ​​by text, use ISO 8601 for reasonable and unambiguous formats.

None of the issues raised in the Question remain. Using an excellent time library and ISO 8601, such as java.time, solves the problem.

Database

Your database should use the date type only for the date of birth and the time type with the timeline for the collection (see SQL Data Types on Wikipedia and in your database documentation). Your JDBC driver alerts you to both types.

In the end, JDBC drivers will be updated to use java.time types directly. But before that, we need to convert java.sql types such as java.sql.Date and java.sql.Timestamp . New methods have been added to old classes to support these transformations.

 java.sql.Date sqlDateOfBirth = java.sql.Date.valueOf( dateOfBirth ); java.sql.Timestamp sqlMeeting = java.sql.Timestamp.valueOf( zdtMontreal ); 

Then call setDate and setTimestamp on the PreparedStatement .

In the other direction, from database to Java, call getDate and getTimestamp on a ResultSet . Then translate immediately to java.time types, avoiding the use of java.sql types in your business logic.

For the date and time value, we must go through the Instant object. Instant is the moment on the timeline in UTC . We use the time zone to get the wall clock for the user.

 LocalDate dateOfBirth = mySqlDate.toLocalDate(); Instant instant = mySqlTimestamp.toInstant(); ZonedDateTime zdtMontreal = ZonedDateTime.ofInstant( instant , zoneIdMontreal ); 
+4
source share

Somehow, two Java systems will need to reconcile Calendar / TimeZone information, or the Date object must be converted to a timestamp when transferred to the remote system.

The easiest way is to simply require all clients to consider their birthday as GMT, when they display / compare / regardless of their birthdays, whether they create a Calendar using "GMT" TimeZone and then setTime() on it with delivered by Date .

If you're working with a model at all, you really need a Date object, not just a timestamp.

+1
source share

For manipulation, I recommend java.util.Calendar

For presentation

Birthday as java.util.Date
NextMeetin as java.sql.Timestamp

+1
source share

This is a very good question ...

Android, for example, stores the birthday as a String in the format "yyyy-MM-dd". I was wondering why they are not using java.util.Date, and I think the reason would be the same problem that you brought here.

Therefore, I would recount either String or some "Timezone-independent-date". But after a few minutes of searching in Java and documentation on joda-time, I have no idea how to do this.

EDIT: It seems @Jeroen is right - use LocalDate.

0
source share

If you are dealing with dates, it is better to use joda time . You can create a DateTime object with date / time and time zone information so that you have all the information needed to process different time zones.

-one
source share

All Articles