Java Time Puzzlers

Preview:

DESCRIPTION

SeaJUG talk with a few puzzles around Joda Time, java.time, and timestamps in general.

Citation preview

This thing all things devours;Birds, beasts, trees, flowers;Gnaws iron, bites steel;Grinds hard stones to meal;Slays king*, ruins town,And beats mountain down.

J.R.R. Tolkien

* and software developer alike

a. sunriseb. sunsetc. could be eitherd. that's no sun!

2010-08-03T03:30Z

a. sunriseb. sunsetc. could be eitherd. that's no sun!

2010-08-03T03:30Z

a. resolve using nearest cityb. resolve using tz_world shapefilec. resolve with Google Maps APId. store the time zone offset

2010-08-03T03:30Z 49.788, -122.987

a. resolve using nearest cityb. resolve using tz_world shapefilec. resolve with Google Maps APId. store the time zone offset

2010-08-03T03:30Z 49.788, -122.987

a. resolve using nearest cityb. resolve using tz_world shapefilec. resolve with Google Maps APId. store the time zone offset

2010-08-03T03:30Z 49.788, -122.987

a. resolve using nearest cityb. resolve using tz_world shapefilec. resolve with Google Maps APId. store the time zone offset

2010-08-03T03:30Z 49.788, -122.987

import org.joda.time.DateTime;

DateTime time = new DateTime("2010-08-02T20:30:00-07:00");

assertEquals(20, time.getHourOfDay());

a. passesb. failsc. throws an exceptiond. it depends

import org.joda.time.DateTime;

DateTime time = new DateTime("2010-08-02T20:30:00-07:00");

assertEquals(20, time.getHourOfDay());

a. passesb. failsc. throws an exceptiond. it depends

import org.joda.time.DateTime;

import org.joda.time.DateTimeZone;

DateTimeZone zone = DateTimeZone.forOffsetHours(-7); DateTime time = new DateTime("2010-08-02T20:30:00-07:00", zone);

assertEquals(20, time.getHourOfDay());

Solution #1Pass an explicit zone to the constructor.

import org.joda.time.DateTime;

import org.joda.time.DateTimeZone;

import org.joda.time.format.DateTimeFormatter;

import org.joda.time.format.ISODateTimeFormat;

DateTimeFormatter fmt = ISODateTimeFormat

.dateTimeNoMillis().withOffsetParsed(); DateTime time = DateTime.parse("2010-08-02T20:30:00-07:00", fmt);

assertEquals(20, time.getHourOfDay());

Solution #2Use a custom formatter.

import java.time.OffsetDateTime;

OffsetDateTime time =

OffsetDateTime.parse("2010-08-02T20:30:00-07:00");

assertEquals(20, time.getHourOfDay());

Solution #3Use java.time.OffsetDateTime

9 hours

a. 5amb. 6amc. too early!d. it depends

When did I get up?

2014-03-08T20:00-08:00

import org.joda.time.DateTime;

import org.joda.time.DateTimeZone;

import org.joda.time.Duration;

DateTimeZone zone = DateTimeZone.forOffsetHours(-8); DateTime time = new DateTime("2014-03-08T20:00:00", zone);

Duration d = Duration.standardHours(9);

assertEquals(6, time.plus(d).getHourOfDay());

a. passesb. failsc. throws an exceptiond. it depends

import org.joda.time.DateTime;

import org.joda.time.DateTimeZone;

import org.joda.time.Duration;

DateTimeZone zone = DateTimeZone.forOffsetHours(-8); DateTime time = new DateTime("2014-03-08T20:00:00", zone);

Duration d = Duration.standardHours(9);

assertEquals(6, time.plus(d).getHourOfDay());

a. passesb. failsc. throws an exceptiond. it depends

import org.joda.time.DateTime;

import org.joda.time.DateTimeZone;

import org.joda.time.Duration;

DateTimeZone zone = DateTimeZone.forID("America/Los_Angeles"); DateTime time = new DateTime("2014-03-08T20:00:00", zone);

Duration d = Duration.standardHours(9);

assertEquals(6, time.plus(d).getHourOfDay());

Don't do math without time zone IDs!

import org.joda.time.DateTime;

import org.joda.time.DateTimeZone;

import org.joda.time.Duration;

import org.joda.time.Period;

DateTimeZone zone = DateTimeZone.forID("America/Los_Angeles"); DateTime time = new DateTime("2014-03-08T20:00:00", zone);

Duration d = Duration.standardDays(1); Period p = Period.days(1);

assertEquals(time.plus(d), time.plus(p));

a. passesb. failsc. throws an exceptiond. it depends

import org.joda.time.DateTime;

import org.joda.time.DateTimeZone;

import org.joda.time.Duration;

import org.joda.time.Period;

DateTimeZone zone = DateTimeZone.forID("America/Los_Angeles"); DateTime time = new DateTime("2014-03-08T20:00:00", zone);

Duration d = Duration.standardDays(1); Period p = Period.days(1);

assertEquals(time.plus(d), time.plus(p));

a. passesb. failsc. throws an exceptiond. it depends

import java.time.DateTime;

import java.time.DateTimeZone;

import java.time.Duration;

import java.time.Period;

ZonedDateTime time = ZonedDateTime

.parse("2014-03-08T20:00:00-08:00[America/Los_Angeles]"); Duration d = Duration.ofDays(1); Period p = Period.ofDays(1);

assertEquals(time.plus(d), time.plus(p));

a. passesb. failsc. throws an exceptiond. it depends

import org.joda.time.DateTime;

import org.joda.time.Duration;

DateTime begin = new DateTime();

// watch me run 100 m

DateTime end = new DateTime();

Duration d = new Duration(begin, end);

assertFalse(d.isShorterThan(Duration.millis(9580)));

a. never failsb. usually failsc. always failsd. TimeOutException

import org.joda.time.DateTime;

import org.joda.time.Duration;

DateTime begin = new DateTime();

// watch me run 100 m

DateTime end = new DateTime();

Duration d = new Duration(begin, end);

assertFalse(d.isShorterThan(Duration.millis(9580)));

a. never failsb. usually failsc. always failsd. TimeOutException

import java.util.concurrent.TimeUnit;

import org.joda.time.Duration;

long begin = System.nanoTime(); // watch me run 100 m

long end = System.nanoTime(); Duration d = Duration.millis( TimeUnit.NANOSECONDS.toMillis(end – begin));

assertFalse(d.isShorterThan(Duration.millis(9580)));

Don't rely on System.currentTimeMillis(),and store an explicit duration.

import org.joda.time.*;

import org.joda.time.Interval;

import org.joda.time.LocalDate;

int steps = 6000;

LocalDate date = LocalDate.parse("2014-11-02"); DateTimeZone zone = DateTimeZone.forID("America/Los_Angeles"); Interval interval = date.toInterval(zone);

long hours = interval.toDuration().getStandardHours();

assertEquals(240, steps / hours);

a. passesb. failsc. exceptiond. it depends

import org.joda.time.*;

import org.joda.time.Interval;

import org.joda.time.LocalDate;

int steps = 6000;

LocalDate date = LocalDate.parse("2014-11-02"); DateTimeZone zone = DateTimeZone.forID("America/Los_Angeles"); Interval interval = date.toInterval(zone);

long hours = interval.toDuration().getStandardHours();

assertEquals(240, steps / hours);

a. passesb. failsc. exceptiond. it depends

Is it a range?

Does local time

matter?

Need to add or subtract

time?

Elapsed time must be

accurate?Store duration

Store with zone offset

Store with zone ID

Store as UTC

Need to storea timestamp

no

no no

no

yes yes

yes yes

for begin and end

Store interval

Start at the beginning, and go on til you come to the end: then stop.

Illustration by John Tenniel, Alice in Wonderland

Recommended