CON4078 Java Time
Transcription
CON4078 Java Time
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