Download CON4078 Java Time

Document related concepts
no text concepts found
Transcript
The Java Time API
What You Need to Know
Angela Caicedo
Java Evangelist
Oracle
Java Day Tokyo 2015
April 8, 2015
Copyright © 2014, Oracle
Copyright
and/or©its2015,
affiliates.
OracleAlland/or
rights its
reserved.
affiliates. All rights reserved. |
Program Agenda
1
Java Time Core API
2
Calendar Neutral API and Regional Calendars
3
Formatting and Localization
4
Tips and Techniques
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
4
Background and History
• JSR 310 started in 2007 by Stephen Colebourne to build on Joda-Time
value and experience
• Integrated into SE 8 Developer Releases in 2013
• SE 8 Final Release in March 2014
• Very successful project to provide a state of the art Calendar API to Java
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
5
Representing Time…
• Human Time
– Year, month, day, hour, minute and second
• Machine Time
– Measures time continuously along a timeline from an origin, called the epoch, in
nanosecond resolution
• Support for both
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
6
Introduction to Java Time
• ISO 8601 Core Calendar – java.time
– LocalTime, LocalDate, LocalDateTime, ZonedDateTime, …
– Clock, Instant, Duration, Period, ZoneId, Month, DayOfWeek, …
– Based on ISO-8601
• Parsing and Formatting – java.time.format
– DateTimeFormat, DateTimeFormatBuilder, standard formats,
patterns, styles, …
• TimeZone – java.time.zone
– ZoneRules, transitions, etc.
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
7
Introduction to Java Time
• Regional Calendars – java.time.chrono
– Chronology, Era, ChronoLocalDate, ChronoLocalDateTime,
ChronoZonedDateTime, …
– Japanese, ThaiBuddhist, Minguo, Hijrah calendars
• Framework – java.time.temporal
– Units, Fields, Adjusters, Temporal, TemporalAccessor,
TemporalAmount, TemporalQuery, …
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
8
Java Time API Design
vs. java.util Date and Calendar
• Fluent API
• Not Fluent
• Immutable instances
• Mutable instances – clone needed
• Thread safe
• Not Thread safe
• Strong types
• Weakly typed calendars
• Fit for purpose types
• One size fits all API
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
9
Date Time API Comparison
Fit for purpose Date Time types
Java.time ISO Calendar
Java.util Calendar
Instant
Date
LocalDate,
Calendar
LocalTime,
LocalDateTime
ZonedDateTime
Calendar
OffsetDateTime, OffsetTime,
Calendar
ZoneId, ZoneOffset, ZoneRules
TimeZone
Week Starts on Monday (1 .. 7)
Week Starts on Sunday (1 .. 7)
enum MONDAY, TUESDAY, … SUNDAY
int values SUNDAY, MONDAY, … SATURDAY
12 Months (1 .. 12)
12 Months (0 .. 11)
enum JANUARY, FEBRUARY, …, DECEMBER
int values JANUARY, FEBRUARY, … DECEMBER
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
10
Design Patterns of Method Names
Consistent naming improves API usability and approachability
Prefix
Method Type
Use
of
static factory
from
static factory
date, dateNow
static factory
Creates an instance where the factory is primarily validating the input parameters,
not converting them
Converts the input parameter to an instance of the target class, which may lose
information from the input
Creates a date from the arguments or from a clock or current time.
parse
static factory
Parses the input string to produce an instance of the target class
format
instance
Uses a formatter to format the values in the temporal object to a string
get
instance
with
instance
Returns a part of the state of the target object
Returns a copy of the target object with one element changed; the immutable
equivalent to set
plus, minus
instance
Returns a copy of the target object with an amount of time added or subtracted
to
instance
Converts this object to another type
at
instance
Combines this object with another
isBefore, isAfter, isEqual
Instance
Compares this object with another on the timeline
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
11
Standard Calendar:
java.time
Based on ISO calendar
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
12
ISO Calendar Types
LocalDate
LocalTime
LocalDateTime
OffsetTime
OffsetDateTime
ZonedDateTime
2010-12-03
11:05:30.987654321
2010-12-03T11:05:30
11:05:30+01:00
2010-12-03T11:05:30+01:00
2010-12-03T11:05:30+01:00 Europe/Paris
Year
YearMonth
MonthDay
2010
2010-12
-12-03
Instant
2576458258.266 seconds after 1970-01-01
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
13
DayOfWeek and Month Enums
• MONDAY through SUNDAY (from 1 -7)
System.out.printf("%s%n", DayOfWeek.MONDAY.plus(3));
THURSDAY
• JANUARY through DECEMBER (1-12)
– maxLength()
System.out.printf("%d%n", Month.FEBRUARY.maxLength());
29
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
14
DayOfWeek
DayOfWeek dow = DayOfWeek.MONDAY;
Locale locale = Locale.getDefault();
System.out.println(dow.getDisplayName(TextStyle.FULL, locale));
System.out.println(dow.getDisplayName(TextStyle.NARROW, locale));
System.out.println(dow.getDisplayName(TextStyle.SHORT, locale));
Monday
M
Mon
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
15
Month
Month month = Month.AUGUST;
Locale locale = Locale.getDefault();
System.out.println(month.getDisplayName(TextStyle.FULL, locale));
System.out.println(month.getDisplayName(TextStyle.NARROW, locale));
System.out.println(month.getDisplayName(TextStyle.SHORT, locale));
August
A
Aug
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
16
LocalDate
• Represents a year-month-day in the ISO calendar without time
LocalDate date = LocalDate.of(2000, Month.NOVEMBER, 20);
LocalDate nextWed = date.with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY));
DayOfWeek dotw = LocalDate.of(2012, Month.JULY, 9).getDayOfWeek();
Monday
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
17
LocalDate
• Finding first Wednesday after specific date
LocalDate date = LocalDate.of(2000, Month.NOVEMBER, 20);
TemporalAdjuster adj = TemporalAdjusters.next(DayOfWeek.WEDNESDAY);
LocalDate nextWed = date.with(adj);
System.out.printf("For the date of %s, the next Wednesday is %s.%n",
date, nextWed);
For the date of 2000-11-20, the next Wednesday is 2000-11-22.
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
18
YearMonth
• lengthOfMonth()
YearMonth date = YearMonth.now();
System.out.printf("%s: %d%n", date, date.lengthOfMonth());
YearMonth date2 = YearMonth.of(2010, Month.FEBRUARY);
System.out.printf("%s: %d%n", date2, date2.lengthOfMonth());
2013-06: 30
2010-02: 28
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
19
MonthDay and Year
MonthDay date = MonthDay.of(Month.FEBRUARY, 29);
boolean validLeapYear = date.isValidYear(2010);
false
boolean validLeapYear = Year.of(2012).isLeap();
true
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
20
LocalTime
• Only deals with time
• Creating digital clock
LocalTime thisSec;
for (;;) {
thisSec = LocalTime.now();
// implementation of display code is left to the reader
display(thisSec.getHour(), thisSec.getMinute(),
thisSec.getSecond());
}
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
21
LocalDateTime
System.out.printf("now: %s%n", LocalDateTime.now());
System.out.printf("Apr 15, 1994 @ 11:30am: %s%n”, LocalDateTime.of(1994,
Month.APRIL, 15, 11, 30));
System.out.printf("now (from Instant): %s%n”,
LocalDateTime.ofInstant(Instant.now(),ZoneId.systemDefault()));
System.out.printf("6 months from now: %s%n”, LocalDateTime.now().plusMonths(6));
System.out.printf("6 months ago: %s%n”, LocalDateTime.now().minusMonths(6));
now: 2013-07-24T17:13:59.985
Apr 15, 1994 @ 11:30am: 1994-04-15T11:30
now (from Instant): 2013-07-24T17:14:00.479
6 months from now: 2014-01-24T17:14:00.480
6 months ago: 2013-01-24T17:14:00.481
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
22
Time Zone and Offset Classes
• Time zone described has:
– The format region/city (Asia/Tokyo)
– An offset from Greenwich/UTC time (+09:00)
• ZoneId
– Specifies a time zone identifier and provides rules for converting between an
Instant and a LocalDateTime.
• ZoneOffset
– Specifies a time zone offset from Greenwich/UTC time.
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
23
Printing a list of all time zones
Set<String> allZones = ZoneId.getAvailableZoneIds();
LocalDateTime dt = LocalDateTime.now();
List<String> zoneList = new ArrayList<String>(allZones);
Collections.sort(zoneList);
// List using the set of zones and sort it.
…
for (String s : zoneList) {
ZoneId zone = ZoneId.of(s);
ZonedDateTime zdt = dt.atZone(zone);
ZoneOffset offset = zdt.getOffset();
int secondsOfHour = offset.getTotalSeconds() % (60 * 60);
String out = String.format("%35s %10s%n", zone, offset);
if (secondsOfHour != 0) {
System.out.printf(out);
}...
}
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
America/Caracas
America/St_Johns
Asia/Calcutta
Asia/Colombo
Asia/Kabul
Asia/Kathmandu
Asia/Katmandu
Asia/Kolkata
Asia/Rangoon
-04:30
-02:30
+05:30
+05:30
+04:30
+05:45
+05:45
+05:30
+06:30
24
Working with Time Zones
• ZonedDateTime
– handles a date and time with a corresponding time zone with a time zone offset from
Greenwich/UTC.
• OffsetDateTime
– handles a date and time with a corresponding time zone offset from Greenwich/UTC,
without a time zone ID.
• OffsetTime
– handles time with a corresponding time zone offset from Greenwich/UTC, without a
time zone ID.
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
25
Flying from San Francisco to Tokyo (1 of 2)
DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM d yyyy hh:mm a");
// Leaving from San Francisco on July 20, 2013, at 7:30 p.m.
LocalDateTime leaving = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
ZoneId leavingZone = ZoneId.of("America/Los_Angeles");
ZonedDateTime departure = ZonedDateTime.of(leaving, leavingZone);
try {
String out1 = departure.format(format);
System.out.printf("LEAVING: %s (%s)%n", out1, leavingZone);
} catch (DateTimeException exc) {
System.out.printf("%s can't be formatted!%n", departure);
throw exc;
LEAVING: Jul 20 2013 07:30 PM (America/Los_Angeles)
}
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
26
Flying from San Francisco to Tokyo (2 of 2)
ZoneId arrivingZone = ZoneId.of("Asia/Tokyo");
// Flight is 10 hours and 50 minutes, or 650 minutes
ZonedDateTime arrival = departure.withZoneSameInstant(arrivingZone).plusMinutes(650);
try {
String out2 = arrival.format(format);
System.out.printf("ARRIVING: %s (%s)%n", out2, arrivingZone);
} catch (DateTimeException exc) {
System.out.printf("%s can't be formatted!%n", arrival);
throw exc; }
if (arrivingZone.getRules().isDaylightSavings(arrival.toInstant()))
System.out.printf(" (%s daylight saving time will be in effect.)%n”, arrivingZone);
else
System.out.printf(" (%s standard time will be in effect.)%n”, arrivingZone);
ARRIVING: Jul 21 2013 10:20 PM (Asia/Tokyo)
(Asia/Tokyo standard time will be in effect.)
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
27
OffsetDateTime: Finding last Thursday in July 2013
LocalDateTime localDate = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
ZoneOffset offset = ZoneOffset.of("-08:00");
OffsetDateTime offsetDate = OffsetDateTime.of(localDate, offset);
OffsetDateTime lastThursday =
offsetDate.with(TemporalAdjusters.lastInMonth(DayOfWeek.THURSDAY));
System.out.printf("The last Thursday in July 2013 is the %sth.%n",
lastThursday.getDayOfMonth());
The last Thursday in July 2013 is the 25th.
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
28
Instant
• Represents the start of a nanosecond on the timeline
• Useful for time stamps
Instant timestamp = Instant.now();
• Instant counts time beginning from the first second of January 1, 1970
(1970-01-01T00:00:00Z) also called the EPOCH.
• Instant before epoch has a negative value, Instant after epoch has a
positive value
• MIN, representing the smallest possible (far past) instant,
• MAX, representing the largest (far future) instant.
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
29
Instant
//Add 1 hour to the current time:
Instant oneHourLater = Instant.now().plusHours(1);
//How many seconds have occurred since the beginning of the Java epoch.
long secondsFromEpoch = Instant.ofEpochSecond(0L).until(Instant.now(),
ChronoUnit.SECONDS);
//Instant to LocalDateTime
Instant timestamp;
LocalDateTime ldt = LocalDateTime.ofInstant(timestamp, ZoneId.systemDefault());
System.out.printf("%s %d %d at %d:%d%n", ldt.getMonth(), ldt.getDayOfMonth(),
ldt.getYear(), ldt.getHour(), ldt.getMinute());
MAY 30 2013 at 18:21
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
30
Temporal Package
• Temporal interface provides methods to add or subtract units of time,
making time-based arithmetic easy and consistent across the various date
and time classes.
• TemporalAccessor interface provides a read-only version of the
Temporal interface.
• ChronoField enum provides a rich set of contants
– DAY_OF_WEEK, MINUTE_OF_HOUR, and MONTH_OF_YEAR.
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
31
TemporalAdjusters
Finding new dates from 15 October 2000
LocalDate date = LocalDate.of(2000, Month.OCTOBER, 15);
DayOfWeek dotw = date.getDayOfWeek();
System.out.printf("%s is on a %s%n", date, dotw);
System.out.printf("first day of Month: %s%n”,
date.with(TemporalAdjusters.firstDayOfMonth()));
System.out.printf("first Monday of Month: %s%n”,
date.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)));
System.out.printf("last day of Month: %s%n”,
date.with(TemporalAdjusters.lastDayOfMonth()));
System.out.printf("first day of next Month: %s%n”,
date.with(TemporalAdjusters.firstDayOfNextMonth()));
System.out.printf("first day of next Year: %s%n”,
date.with(TemporalAdjusters.firstDayOfNextYear()));
2000-10-15 is on a SUNDAY
first day of Month: 2000-10-01
first Monday of Month: 2000-10-02
last day of Month: 2000-10-31
2014,next
Oracle and/or
its affiliates. All2000-11-01
rights reserved.
firstCopyright
day©of
Month:
32
Custom Adjusters
• Create a class implementing TemporalAdjuster
– adjustInto(Temporal) method
• Example
– Create an adjuster that evaluates the passed-in date and returns the next payday,
assuming that payday occurs twice a month: on the 15th, and again on the last day of
the month. If the computed date occurs on a weekend, then the previous Friday is
used.
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
33
PayDay (1 of 2)
public Temporal adjustInto(Temporal input) {
LocalDate date = LocalDate.from(input);
int day;
if (date.getDayOfMonth() < 15) {
day = 15;
} else {
day=date.with(TemporalAdjusters.lastDayOfMonth()).
getDayOfMonth();
}
date = date.withDayOfMonth(day);
if (date.getDayOfWeek() == DayOfWeek.SATURDAY ||
date.getDayOfWeek() == DayOfWeek.SUNDAY) {
date = date.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
}
return input.with(date);
}
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
34
PayDay (2 of 2)
LocalDate nextPayday = date.with(new PaydayAdjuster());
In 2013, both June 15 and June 30 occur on the weekend.
Given the date: 2013 Jun 3
the next payday: 2013 Jun 14
Given the date: 2013 Jun 18
the next payday: 2013 Jun 28
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
35
Predefined Queries: TemporalQueries
TemporalQueries query = TemporalQueries.precision();
System.out.printf("LocalDate precision is %s%n”, LocalDate.now().query(query));
System.out.printf("LocalDateTime precision is %s%n”,
LocalDateTime.now().query(query));
System.out.printf("Year precision is %s%n”, Year.now().query(query));
System.out.printf("YearMonth precision is %s%n", YearMonth.now().query(query));
System.out.printf("Instant precision is %s%n”, Instant.now().query(query));
LocalDate precision is Days
LocalDateTime precision is Nanos
Year precision is Years
YearMonth precision is Months
Instant precision is Nanos
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
36
Custom Queries
• Implements the TemporalQuery interface
– queryFrom(TemporalAccessor)
//checking if a date is during vacation
public Boolean queryFrom(TemporalAccessor date) {
int month = date.get(ChronoField.MONTH_OF_YEAR);
int day
= date.get(ChronoField.DAY_OF_MONTH);
// Disneyland over Spring Break
if ((month == Month.APRIL.getValue()) && ((day >= 3) && (day <= 8)))
return Boolean.TRUE;
// Smith family reunion on Lake Saugatuck
if ((month == Month.AUGUST.getValue()) && ((day >= 8) && (day <= 14)))
return Boolean.TRUE;
return Boolean.FALSE;
}
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
37
Period and Duration
• Duration measures an amount of time using time-based values
(seconds, nanoseconds).
– Instant object
– Can be negative: End point occurs before start point
• Period uses date-based values (years, months, days).
– A Duration of one day is exactly 24 hours long.
– A Period of one day, when added to a ZonedDateTime, may vary according to
the time zone (first or last day of daylight saving time)
• ChronoUnit defines the units used to measure time
– between()
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
38
Duration & ChronoUnit
Instant t1, t2;
...
long ns = Duration.between(t1, t2).toNanos();
//Add 10 seconds to an Instant:
Instant start;
...
Duration gap = Duration.ofSeconds(10);
Instant later = start.plus(gap);
Instant previous, current, gap;
...
current = Instant.now();
if (previous != null) {
gap = ChronoUnit.MILLIS.between(previous,current);
}
...
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
39
Period: How old are you?
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(1960, Month.JANUARY, 1);
Period p = Period.between(birthday, today);
long p2 = ChronoUnit.DAYS.between(birthday, today);
System.out.println("You are " + p.getYears() + " years, " +
p.getMonths() +
" months, and " + p.getDays() +
" days old. (" + p2 + " days total)");
You are 53 years, 4 months, and 29 days old. (19508 days total)
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
40
Period: How long to your next birthday?
LocalDate birthday = LocalDate.of(1960, Month.JANUARY, 1);
LocalDate nextBDay = birthday.withYear(today.getYear());
//If your birthday has occurred this year already, add 1 to the year.
if (nextBDay.isBefore(today) || nextBDay.isEqual(today)) {
nextBDay = nextBDay.plusYears(1);
}
Period p = Period.between(today, nextBDay);
long p2 = ChronoUnit.DAYS.between(today, nextBDay);
System.out.println("There are " + p.getMonths() + " months, and " +
p.getDays() + " days until your next birthday. (" +
p2 + " total)");
There are 7 months, and 2 days until your next birthday. (216 total)
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
41
Calendar Neutral API
and Regional Calendars
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
42
Calendar Neutral API
• The core java.time APIs are designed to avoid common errors
• For other calendars common assumptions may be invalid
– Don't assume the number of months of year
– Use the API to do all calendar arithmetic. Plus/minus days, months, years
– Do not assume roll-over at particular numbers of days-per-month or months-per-year
– Don't assume the week starts on Monday (ISO), use WeekFields.
– Don't assume the month numbers are bound to specific months, use
DateTimeFormatter to get names
• A Chronology is added to provide the correct semantics for the calendar
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
43
Converting to a Non-ISO-Based Date
LocalDateTime date = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
JapaneseDate jdate = JapaneseDate.from(date);
HijrahDate hdate = HijrahDate.from(date);
MinguoDate mdate = MinguoDate.from(date);
ThaiBuddhistDate tdate = ThaiBuddhistDate.from(date);
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
44
Calendar Neutral Dates
import static java.time.temporal.ChronoField.*;
import static java.time.temporal.ChronoUnit.*;
Locale locale = …;
Chronology chrono = Chronology.ofLocale(locale);
ChronoLocalDate date = chrono.dateNow();
int
int
int
Era
day
month
year
era
=
=
=
=
date.get(DAY_OF_MONTH);
date.get(MONTH_OF_YEAR);
date.get(YEAR_OF_ERA);
date.get(ERA)
ChronoLocalDate nextmonth = date
.with(DAY_OF_MONTH, 1)
.plus(1, MONTHS);
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
45
Calendar Neutral Dates, Times, and Time Zones
Chronology chrono = …;
ChronoLocalDate date = chrono.dateNow();
// Calendar neutral dates and times combinations.
ChronoLocalDateTime<?> cldt = date.atTime(LocalTime.NOON);
ChronoLocalDate d = cldt.toLocalDate();
LocalTime t = cldt.toLocalTime();
ZoneId zone = ZoneId.of(“Europe/Paris");
ChronoZonedDateTime<?> czdt = cldt.atZone(zone);
czdt = czdt.with(LocalTime.MIDNIGHT);
Output:
2013-10-01T00:00+02:00[Europe/Paris]
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
46
Calendar Neutral API Mapping
Accessed by Fields and Units
Java.time.temporal.ChronoField
Java.time.temporal.ChronoUnits
ChronoField.DAY_OF_MONTH
ChronoUnit.DAYS
ChronoField.MONTH_OF_YEAR
ChronoUnit.MONTHS
ChronoField.YEAR
ChronoUnit.YEARS
ChronoField.HOUR_OF_DAY
ChronoUnit.HOURS
ChronoField.MINUTE_OF_HOUR
ChronoUnit.MINUTES
ChronoField.SECOND_OF_DAY
ChronoUnit.SECONDS
ChronoField.MILLI_OF_SECOND
ChronoUnit.MILLIS
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
47
Regional Calendars
Listing, lookup, creating dates
Set<Chronology> chronologies =
Chronology.getAvailableChronologies();
for (Chronology chrono : chronologies) {
System.out.printf(" %s (%s)%n",
chrono.getId(), chrono.getCalendarType());
}
ISO (iso8601)
Hijrah-umalqura (islamic-umalqura)
ThaiBuddhist (buddhist)
Japanese (japanese)
Minguo (roc)
// Lookup by name or CLDR type
Chronology chrono = Chronology.of("Hijrah");
chrono = Chronology.of("islamic-umalqura");
Hijrah-umalqura (islamic-umalqura)
// Select calendar based on BCP47 locale language tags
Locale locale =
Locale.forLanguageTag("ja-JP-u-ca-japanese");
chrono = Chronology.ofLocale(locale);
// Create date based on proleptic year, month, day
ChronoLocalDate date = chrono.date(2014, 9, 29);
Japanese (japanese)
Japanese Heisei 26-09-29
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
48
Japanese Date, Eras and Chronology
static import java.time.chrono.JapaneseEra.HEISEI;
Locale locale = Locale.forLanguageTag("ja-JP-u-ca-japanese");
ZoneId zone = ZoneId.of("Asia/Tokyo");
JapaneseDate jdate = JapaneseDate.of(HEISEI, 25, 9, 22);
ChronoLocalDateTime<JapaneseDate> jldt = jdate.atTime(LocalTime.now());
ChronoZonedDateTime<JapaneseDate> jzdt = jldt.atZone(zone);
jzdt = jzdt.plus(2, ChronoUnit.DAYS);
czdt.format(DateTimeFormatter
.ofPattern("GGGGyy-mm-dd")
.withLocale(locale))
Output: 平成25-09-24
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
49
Formatting and Localization
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
50
DateTimeFormatter Builder
Customizing parsing and formatting
• Factory used to build a template for a sequence of fields to be parsed or formatted
• Literals, for example “/”, “-”, “:”, or any string
• Numeric values with control of width, sign, leading zeros
• Text indexed by locale and style – short, narrow, full, standalone
• Patterns indexed by locale - date, time, date-time
• Fraction control, with control of width and decimal points
• Field padding to width and character
• ZoneId, ZoneOffset, Chronology, Instant specialized fields
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
51
DateTimeFormatter Builder II
• Case sensitive vs. in-sensitive parsing
• Optional fields
• Default values if not present in input
• Strict vs. Lenient parsing mode
• Concatenation of Formatters
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
52
Formatter Builder Example
Parse time with optional minutes and seconds
DateTimeFormatter format = new DateTimeFormatterBuilder()
.appendValue(HOUR_OF_DAY, 1, 2, SignStyle.NEVER)
.optionalStart()
.appendLiteral(":").appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(":").appendValue(SECOND_OF_MINUTE, 2)
.optionalEnd()
.optionalEnd()
.parseDefaulting(MINUTE_OF_HOUR, 1)
.parseDefaulting(SECOND_OF_MINUTE, 0)
.toFormatter();
LocalTime date = LocalTime.parse(s, format);
System.out.printf(" Parsed %10s --- %7s%n", s, date.format(fmt));
Output:
Parsed
Parsed
Parsed
Parsed
9
09:05
09:30:59
23:00
→
→
→
→
9:01:00
9:05:00
9:30:59
23:00:00
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
53
Formatting Patterns
Format vs. DateTimeFormat vs. SimpleDateFormat
Formatter Letter
%tx and %Tx
G
y
M
L
w
W
D
d
E
CLDR Pattern Letters
DateTimeFormatter
G
y
M
L
w
W
D
d
E
u
e
M
S
L
a
H
k
m
s
S
a
H
k
m
s
S
Z, z
z , Z, X
Y, y, C
B, b, h, m
B, b, h, m
j
D, e
A, a
p
H, k
SDF Pattern Letter
Date or Time Component
Examples
Era designator
Year –of-Era
Month in year (context sensitive)
Month in year (standalone form)
Week in year
Week in month
Day in year
Day in month
Day name in week
Day number in week
(1 = Monday .. 7 = Sunday)
Am/pm marker
Hour in day (0-23)
Hour in day (1-24)
Minute in hour
Second in minute
Millisecond / Fraction of Second
AD
1996; 96
July; Jul; 07
July; Jul; 07
27
2
189
10
Tuesday; Tue
Time zone
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
1
PM
0
24
30
55
978
Pacific Standard Time; PST; GMT-08:00
; -0800 ; -08; -0800; -08:00
54
java.util.Formatter supports Java Time types String.format, PrintStream.format, …
Locale locale = Locale.getDefault();
Formatter fmt = new Formatter(System.out, locale);
Date date = new Date();
Calendar cal = Calendar.getInstance();
LocalDate ld = LocalDate.now();
LocalTime lt = LocalTime.now();
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ZonedDateTime.now();
fmt.format("date:
%tc%n", date);
fmt.format(" cal:
%tc%n", cal);
fmt.format("ZonedDateTime: %tc%n", zdt);
date:
Fri Sep 19 15:16:33 EDT 2014
cal:
Fri Sep 19 15:16:33 EDT 2014
ZonedDateTime: Fri Sep 19 15:16:33 EDT 2014
LocalDate: Fri Sep 19 2014
fmt.format("
LocalDate: %1$ta %1$tb %1$td %1$tY%n", ld);
LocalTime: 15:16:33
fmt.format("
LocalTime: %tT %n", lt);
fmt.format("LocalDateTime: %1$ta %1$tb %1$td %1$tT %1$tY%n", ldt); LocalDateTime: Fri Sep 19 15:16:33 2014
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
55
Predefined Date Time Formats
ZonedDateTime now = ZonedDateTime.now();
String toString = now.toString();
// 2013-08-06T18:12:17.423-04:00[America/New_York]
DateTimeFormatter format =
DateTimeFormatter.ISO_ZONED_DATE_TIME;
String s = now.format(format);
// 2013-08-06T18:12:17.423-04:00[America/New_York]
Formatter
Example
ofLocalizedDateTime(
3 Jun 2008 11:05
dateStyle, timeStyle)
BASIC_ISO_DATE
20111203
ISO_LOCAL_DATE
2011-12-03
ISO_OFFSET_DATE
2011-12-03+01:00
ISO_DATE
2011-12-03+01:00; 2011-12-03
ISO_LOCAL_TIME
10:15:30
ISO_OFFSET_TIME
10:15:30+01:00
ISO_TIME
10:15:30+01:00; 10:15:30
ISO_LOCAL_DATE_TIME
2011-12-03T10:15:30
ISO_OFFSET_DATE_TIME 2011-12-03T10:15:30+01:00
ISO_ZONED_DATE_TIME
2011-12-03T10:15:30+01:00[Europe/Paris]
ISO_INSTANT
2011-12-03T10:15:30Z
RFC_1123_DATE_TIME
Tue, 3 Jun 2008 11:05:30 GMT
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
56
DateTimeFormatter Predefined and Customizable Patterns
import static
java.time.format.DateTimeFormatter.*;
ZonedDateTime now = ZonedDateTime.now();
now.toString();
2013-08-09T15:20:40.167-04:00[America/New_York]
now.format(RFC_1123_DATE_TIME)
now.format(ISO_DATE_TIME)
now.format(ofLocalizedDateTime(FormatStyle.FULL))
Fri, 9 Aug 2013 15:20:40 -0400
2013-08-09T15:20:40.167-04:00[America/New_York]
Friday, August 9, 2013 3:20:40 PM EDT
now.format(ofPattern("z zz zzz zzzz VV"))
EDT EDT EDT Eastern Daylight Time America/New_York
now.format(ofPattern("y'-W'w-e"))
now.format(ofPattern("h:ss a"))
now.format(ofPattern("'Q'q y"))
2013-W37-3
4:02 PM
Q3 2013
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
57
Locale based Date and Time formats –
Use DateTimeFormatter instead of SimpleDateFormat
Immutable and thread safe formatting
Locale locale = …;
GregorianCalendar cal = new GregorianCalendar();
Locale locale = …;
Calendar cal = Calendar.getInstance();
DateTimeFormatter dtf = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.MEDIUM,
FormatStyle.MEDIUM)
.withLocale(locale);
SimpleDateFormat sdf
= (SimpleDateFormat)DateFormat
.getDateTimeInstance(SimpleDateFormat.MEDIUM,
SimpleDateFormat.MEDIUM, locale);
ZonedDateTime zdt = cal.toZonedDateTime();
dtf.format(zdt);
Date date = cal.getTime();
sdf.format(date);
Output:
Sep 19, 2014 3:26:10 PM
Output:
Sep 19, 2014 3:26:10 PM
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
58
DatePicker Control in JavaFX
 Settable Chronology
 Supports Regional Formatting via
Locale
 Customizable Cell Factory
import javafx.scene.control.DatePicker;
datePicker = new DatePicker();
datePicker.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent t) {
LocalDate isoDate = datePicker.getValue();
println("Selected date: “ + isoDate);
}
});
Output:
Selected date: 2013-09-23
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
59
Summary
New Improved Date Time API
• Fluent, Immutable, Thread Safe, Easy to use
• Strong typing with fit for purpose types
• Easy to use formatting and parsing
• Extensible with Units, Fields, and Chronologies
• Interoperable with java.util.Calendar
• Supports Regional Calendars
• The essential ISO Calendar for global business
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
60
Q &A
Threeten Articles and References
– http://www.threeten.org/links.html
• Java™ Date Time Tutorials
– http://docs.oracle.com/javase/tutorial/datetime
• Java™ Standard Edition API
– http://docs.oracle.com/javase/8/docs/api
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
61
Safe Harbor Statement
The preceding is intended to outline our general product direction. It is intended for
information purposes only, and may not be incorporated into any contract. It is not a
commitment to deliver any material, code, or functionality, and should not be relied upon
in making purchasing decisions. The development, release, and timing of any features or
functionality described for Oracle’s products remains at the sole discretion of Oracle.
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
62
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.
63