# Challenges of Date and Time Processing

• Historically, a second was derived from Earth's rotation around its axis.
• There are 24 × 60 × 60 = 86400 per revolution.
• Nowadays a second is derived from an intrinsic property of caesium atoms (measured by “atomic clocks”).
• Ever so often, leap seconds are inserted.
• The Java API keeps the number seconds per day constant and instead stretches them slightly.
• Other complexities are created by humans:
• Variable month lengths
• Weekdays
• Time zones

# Instants

• An `Instant` is a point on the time line.
• Arbitrary origin at midnight of January 1, 1970 UTC (or “Greenwich Mean Time”).
• UTC stands for “Coordinated Universal Time”. The acronym is a compromise between the English and the French “Temps Universel Coordiné,” being incorrect in either language.
• From that origin, instants are measured in seconds, to nanosecond precision.
• `Instant.MIN` is a billion years before January 1, 1970, and `Instant.MAX` is a billion years later.
• `Instant.now()` yields the current instant.

# Durations

• A `Duration` is the difference between two instants.
• Measuring the running time of an algorithm:
```Instant start = Instant.now();
runAlgorithm();
Instant end = Instant.now();
Duration timeElapsed = Duration.between(start, end);
long millis = timeElapsed.toMillis();```
• Conversely, you can adjust an `Instant` by a `Duration`:
```Instant start = Instant.now();
Instant later = start.plus(Duration.ofHours(8));
```
• `Instant` and `Duration` are immutable.
• The `plus` method returns a new `Instant` object.
• Other methods for arithmetic and comparisons:
```boolean overTenTimesFaster
= timeElapsed.multipliedBy(10).minus(timeElapsed2).isNegative();```
• Usually simpler to work with nanoseconds:
```boolean overTenTimesFaster
= timeElapsed.toNanos() * 10 < timeElapsed2.toNanos()```

# Local Dates

• A `LocalDate` is a calendar date without a time zone.
• Alonzo Church, inventor of the lambda calculus, was born on June 14, 1903.
• Construct a `LocalDate` with one of the factory methods:
```LocalDate today = LocalDate.now(); // Today’s date
LocalDate alonzosBirthday = LocalDate.of(1903, Month.JUNE, 14);```
• Methods `plusDays`, `plusWeeks`, `plusMonths`, `plusYears` (and `minus`Xxx):
```LocalDate programmersDay = LocalDate.of(2016, 1, 1).plusDays(255);
```
• To find the number of days between two dates, call:
```int days = independenceDay.until(christmas, ChronoUnit.DAYS); // 174 days
```
• Caution: Calling `plusMonths` can yield implausible results.
• `LocalDate.of(2016, 1, 31).plusMonths(1)` yields February 29, 2016.

# jshell

```import java.time.*

LocalDate today = LocalDate.now()
today.plusDays(100)
today.plusDays(1000)
LocalDate birthday = LocalDate.of(1961, 8, 4)

import java.time.temporal.*

birthday.until(today, ChronoUnit.DAYS)
```

# Weekdays

• The `getDayOfWeek` method yields the weekday of a `LocalDate`:
`DayOfWeek weekday = LocalDate.of(1900, Month.JANUARY, 1).getDayOfWeek();`
• `DayOfWeek.MONDAY` has numerical value 1, and `DayOfWeek.SUNDAY` has value 7:
```int value = weekday.getValue();
```
• Note that the weekend comes at the end!
• `DayOfWeek` can do arithmetic modulo 7:
• `DayOfWeek.SATURDAY.plus(3)` yields `DayOfWeek.TUESDAY`

• For scheduling applications, you may need to compute dates such as “the first Tuesday of every month.”
• The `TemporalAdjusters` class provides a number of static methods for common adjustments.
• Compute the first Tuesday of a month:
```LocalDate firstTuesday = LocalDate.of(year, month, 1).with(
• You can make your own adjusters:
```TemporalAdjuster NEXT_WORKDAY = TemporalAdjusters.ofDateAdjuster(w -> {
LocalDate result = w;
do {
result = result.plusDays(1);
} while (result.getDayOfWeek().getValue() >= 6);
return result;
});```
• Pass the adjuster to the `next` or `nextOrSame` method:
```LocalDate firstWorkday = LocalDate.of(year, 1, 1).with(NEXT_WORKDAY);
```

# Local Time

• A `LocalTime` represents a time of day, such as 22:30:00
• Create an instance with a factory method:
```LocalTime rightNow = LocalTime.now();
LocalTime bedtime = LocalTime.of(22, 30, 0);```
• There are methods to add hours, minutes, seconds, or nanoseconds:
```LocalTime wakeup = bedtime.plusHours(8);
```
• `LocalTime` doesn't concern itself with AM/PM—that is left to formatters.
• There is also a `LocalDateTime` for a timezone-independent date and time.

# Zoned Time

• Timezones are messy and, in theory, unnecessary.
• If some of us ate lunch at 02:00 and others at 22:00, our stomachs would figure it out.
• It works in China, which uses one time zone for an area that spans four conventional time zones.
• Australia, which is smaller, has five time zones, some with 30 and 45 minute offsets.
• The `ZonedDateTime` class handles the messiness.
• Each time zone has an officially assigned ID.
• `ZoneId.getAvailableIds()` lists them all.
• Get a `ZonedDateTime` like this:
```ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime apollo11launch = ZonedDateTime.of(1969, 7, 16, 9, 32, 0, 0,
ZoneId.of("America/New_York"));```
• A `ZonedDateTime` is a specific point in time. Can convert to/from `Instant`:
```Instant launchInstant = apollo11launch.toInstant();
ZonedDateTime launchInUTC = instant.atZone(ZoneId.of("UTC"));
```

# Daylight Savings Time

• What could be worse than time zones? Daylight savings time!
• Daylight savings time starts and ends at different times across the world.
• The rules change over time.
• `ZonedDateTime` handles the rules, as published in the volunteer-maintained “tz database”
• Beware of times that don't exist:
```ZonedDateTime skipped = ZonedDateTime.of(
2013, 3, 31, 2, 30, 0, 0, ZoneId.of("Europe/Berlin"));
// Constructs March 31 3:30—Central Europe switched to DST at 2:00```
• Beware of adjusting a date across daylight savings time boundaries:
```ZonedDateTime nextMeeting = meeting.plus(Duration.ofDays(7));
// Caution! Won’t work with daylight savings time```
• Instead, use the `Period` class:
`ZonedDateTime nextMeeting = meeting.plus(Period.ofDays(7)); // OK`

# jshell

```ZonedDateTime.now()
ZonedDateTime.now(ZoneId.of("UTC"))
ZonedDateTime.now(ZoneId.of("Europe/Rome"))

ZonedDateTime.now().plus(Duration.ofDays(90))
ZonedDateTime.now().plus(Period.ofDays(90))
```

# Legacy Date and Time Classes

• `java.time` is the third attempt at a date/time library for Java.
• Java 1.0 introduced a `java.util.Date` class.
• Equivalent to the `java.time.Instant` class.
• `Date` has mutators and deprecated methods for the Gregorian calendar.
• Java 1.1 introduced a `java.util.Calendar` class and a subclass `GregorianCalendar`.
• Equivalent to the `java.time.ZonedDateTime` class.
• `Calendar` has mutators and a cumbersome API.
• Convert between `java.util.Date` and `Instant` with the static method `Date.from(Instant)` and the method `Date.toInstant()`.
• Convert between `GregorianCalendar` and `ZonedDateTime` with the static method `GregorianCalendar.from(ZonedDateTime)` and the method `GregorianCalendar.toZonedDateTime()`.
• The `java.sql` package has `Date`, `Time`, and `Timestamp` classes that are equivalent to the `LocalDate`, `LocalTime`, and `Instant` classes.
• Use the static `valueOf` methods and the methods `Date.toLocalDate`, `Time.toLocalTime` for conversions between SQL`Date`/`Time` and `LocalDate`/`LocalTime`.
• Use the static `Timestamp.from` method and the `Timestamp.toInstant` methods to convert between the `Timestamp` and `Instant` classes.