Appearance
Best Practices
Java offers two sets of date and time APIs. Unless dealing with legacy code, it's best to stick with the new API. However, if you need to convert between them, here's how:
Old API to New API
To convert old Date
or Calendar
objects to the new API, you can use the toInstant()
method to get an Instant
, which can then be converted to ZonedDateTime
:
java
// Date -> Instant:
Instant ins1 = new Date().toInstant();
// Calendar -> Instant -> ZonedDateTime:
Calendar calendar = Calendar.getInstance();
Instant ins2 = calendar.toInstant();
ZonedDateTime zdt = ins2.atZone(calendar.getTimeZone().toZoneId());
You can see that the old TimeZone
provides a toZoneId()
method to convert to the new ZoneId
.
New API to Old API
To convert ZonedDateTime
back to the old API, you can use a long timestamp as an intermediary:
java
// ZonedDateTime -> long:
ZonedDateTime zdt = ZonedDateTime.now();
long ts = zdt.toEpochSecond() * 1000; // Convert to milliseconds
// long -> Date:
Date date = new Date(ts);
// long -> Calendar:
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.setTimeZone(TimeZone.getTimeZone(zdt.getZone().getId()));
calendar.setTimeInMillis(ts);
Storing Dates and Times in Databases
Apart from java.util.Date
, there's java.sql.Date
, which ignores time-related information. In databases, there are several types for storing date and time:
- DATETIME: Represents date and time.
- DATE: Represents only the date.
- TIME: Represents only the time.
- TIMESTAMP: Similar to DATETIME but updates automatically on record creation or update.
Here's how these database types map to Java classes:
Database Type | Corresponding Java Class (Old) | Corresponding Java Class (New) |
---|---|---|
DATETIME | java.util.Date | LocalDateTime |
DATE | java.sql.Date | LocalDate |
TIME | java.sql.Time | LocalTime |
TIMESTAMP | java.sql.Timestamp | LocalDateTime |
The most common type to store in a database is Instant
, as it allows you to display the correct local time based on the user's timezone. It's best to store this as a long integer (e.g., BIGINT
).
You can create a timestampToString()
method to display different local times based on preferences:
java
import java.time.*;
import java.time.format.*;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
long ts = 1574208900000L;
System.out.println(timestampToString(ts, Locale.CHINA, "Asia/Shanghai"));
System.out.println(timestampToString(ts, Locale.US, "America/New_York"));
}
static String timestampToString(long epochMilli, Locale lo, String zoneId) {
Instant ins = Instant.ofEpochMilli(epochMilli);
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT);
return f.withLocale(lo).format(ZonedDateTime.ofInstant(ins, ZoneId.of(zoneId)));
}
}
Summary
- Always prefer the new
java.time
package for date and time handling. - When storing timestamps in a database, using a long integer provides space efficiency and high performance without relying on the database's date/time types.