Understanding Date and Time Handling in Java: From System.currentTimeMillis to Java 8 Date/Time API
This article explains the physical and philosophical notions of time, the challenges of representing time in computing, and provides a comprehensive guide to Java's date‑time APIs—including System.currentTimeMillis, System.nanoTime, java.util.Date, java.sql.Timestamp, Calendar, SimpleDateFormat, and the modern Java 8 classes such as Instant, LocalDate/Time, ZonedDateTime, and DateTimeFormatter—while highlighting common pitfalls and best practices.
Time is both a physical scalar used to order events and a philosophical construct, and computer systems must map these concepts to Earth’s rotation, time zones, daylight‑saving rules, and standardized timestamps.
1 Common Knowledge
Time zones define a uniform time for a geographic region; daylight‑saving time (DST) shifts clocks forward by one hour in summer; UTC (Coordinated Universal Time) is a second‑based standard maintained by international bodies, while GMT is an astronomical reference. UTC is more precise than GMT and may require leap seconds.
2 Java Date‑Time Retrieval, Representation, and Conversion
2.1 System.currentTimeMillis()
This static method returns the number of milliseconds since the Unix epoch (1970‑01‑01 00:00:00 UTC). Long time = System.currentTimeMillis(); Note: the method’s granularity depends on the underlying OS and may affect performance in high‑concurrency scenarios.
2.2 System.nanoTime()
Provides a high‑resolution time source for measuring elapsed time, unrelated to wall‑clock time.
Long startTime = System.nanoTime();
// doSomething();
Long elapsed = System.nanoTime() - startTime;2.3 java.util.Date
The original mutable date class stores a Unix timestamp (fastTime) and a cached BaseCalendar.Date (cdate). Constructors:
public Date() { this(System.currentTimeMillis()); }
public Date(long date) { fastTime = date; }Key methods include getTime(), setTime(), after(), before(), compareTo(), and equals().
2.4 java.sql.Date, Time, Timestamp
These subclasses of java.util.Date are used for JDBC. Timestamp adds a nanos field for sub‑millisecond precision, but its nanosecond component may be “fake” because it is derived from the millisecond value.
public Timestamp(long time) {
super((time/1000)*1000);
nanos = (int)((time%1000) * 1000000);
if (nanos < 0) {
nanos = 1000000000 + nanos;
super.setTime(((time/1000)-1)*1000);
}
}Timestamp.equals(Object) is not symmetric with java.util.Date.equals(Object), and after() inherited from Date can give incorrect results when only millisecond differences exist.
2.5 java.util.Calendar
Calendar is an abstract class that handles locale‑specific calendars (Gregorian, Buddhist, Japanese, etc.). Instances are obtained via Calendar.getInstance() or by constructing a subclass such as new GregorianCalendar(). It provides methods to get and set individual fields, add/subtract units, and convert to java.util.Date or Unix timestamps.
Calendar calendar = Calendar.getInstance();
System.out.println(calendar);Important notes: months are zero‑based, days of week start at 1 (Sunday), and constants like Calendar.JANUARY should be used.
2.6 java.text.SimpleDateFormat
SimpleDateFormat formats and parses dates according to a pattern but is not thread‑safe because it holds a mutable Calendar. In multithreaded environments it can cause parsing failures.
Typical solutions:
Create a new instance per request.
Synchronize parse/format calls.
Use a ThreadLocal to cache a formatter per thread.
private static ThreadLocal<DateFormat> sdfThreadLocal = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
public static void main(String[] args) {
for (int i = 0; i < 100; ++i) {
new Thread(() -> {
try {
System.out.println(sdfThreadLocal.get().parse("2019-08-04 22:17:27"));
} catch (Exception e) {
System.out.println("Parse failed");
}
}).start();
}
}2.7 Java 8 Date‑Time API
Java 8 introduces immutable, thread‑safe classes: Instant, LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Period, Duration, and DateTimeFormatter. Instant represents a point on the UTC timeline with nanosecond precision. LocalDate, LocalTime, and LocalDateTime represent date, time, or both without time‑zone information. ZonedDateTime combines a LocalDateTime with a ZoneId and ZoneOffset to handle time zones. DateTimeFormatter replaces SimpleDateFormat and is thread‑safe. Period works with dates, while Duration works with time‑based amounts.
These new types simplify common tasks such as adding days, converting between zones, and calculating differences, and they avoid the mutability and thread‑safety problems of the legacy API.
Key Takeaways
Legacy classes ( Date, Calendar, SimpleDateFormat) are mutable and often error‑prone.
Use the Java 8 date‑time API for new development; it provides clear separation of concerns, immutability, and built‑in time‑zone handling.
When interacting with databases, be aware of the subtle differences between java.sql.Timestamp and java.util.Date, especially regarding equality and precision.
For high‑performance or multithreaded code, prefer Instant and Duration for elapsed‑time measurement instead of System.currentTimeMillis() or System.nanoTime() directly.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
