Copyright © Cay S. Horstmann 2016

- 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

- 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.

- 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.

- The
- 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()

- 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.

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)

- 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 week
**end**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( TemporalAdjusters.nextOrSame(DayOfWeek.TUESDAY));

- 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);

- 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.

- 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"));

- 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

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))

`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.

- Equivalent to the
- 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.

- Equivalent to the
- 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.

- Use the static