Package com.neiljbrown.examples.java8

Source Code of com.neiljbrown.examples.java8.DateTimeExamplesTest

/*
* Copyright 2014-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.neiljbrown.examples.java8;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.*;

import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.MonthDay;
import java.time.Period;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;

import org.junit.Test;

/**
* Examples of the new, improved <a href="http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html">Date
* and Time API</a> available in Java 8, implemented as a JUnit test case.
*
* <h2>Local and Time Zone Date/Times</h2>
* <p>
* The API has two separate categories of date/time classes - local and zoned.
* <p>
* Local date/time time classes ({@link LocalDateTime}, {@link LocalDate} and {@link LocalTime}) are “local” in the
* sense that they don’t have any time zone context, and are akin to how people think of their (local) time.
* <p>
* A {@link ZonedDateTime} has a contextual time-zone. Use this class (rather than LocalDateTime) if you want to
* represent a date and time without relying on the time-zone of a specific server.
*
* <h2>Further Reading</h2>
* <p>
* <a href="http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html">JSE 8 Date and Time (overview),
* Evans and Warburton, 02/2014</a> <br>
* <a href="http://docs.oracle.com/javase/tutorial/datetime/index.html">Date and Time, Oracle Java Tutorial</a>
*/
public class DateTimeExamplesTest {

  /**
   * Date/time classes provide factory methods which follow naming conventions. of() is used to construct date/time from
   * their constituent field, from a year, up to a resolution of nanoseconds.
   */
  @Test
  public void testCreateDateTimeFromConstituentFields() {
    final LocalDateTime localDateTime = LocalDateTime.of(2014, Month.AUGUST, 30, 21, 40, 20);
    // toString() methods return ISO-8601 format representation by default, which is consistent with parsing (see below)
    assertThat(localDateTime.toString(), is("2014-08-30T21:40:20"));
  }

  /**
   * Date/time classes provide factory methods which follow naming conventions. parse() is used to construct date/time
   * from, by default an ISO-8601 format string.
   * <p>
   * Parse methods use the {@link java.time.format.DateTimeFormatter} which has constants for the supported date/time
   * string formats.
   */
  @Test
  public void testParseDateTime() {
    // Parse a local (no time zone) date/time string
    // Uses java.time.format.DateTimeFormatter#ISO_LOCAL_DATE_TIME.
    final LocalDateTime localdateTime = LocalDateTime.parse("2014-08-30T21:40:20");
    assertThat(localdateTime, is(LocalDateTime.of(2014, Month.AUGUST, 30, 21, 40, 20)));

    // Parse a date/time string with a time zone, in ISO-8601 format - this one is in UTC, as per the 'Z' zone indicator
    // Uses java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME.
    final ZonedDateTime zonedDateTime = ZonedDateTime.parse("2014-08-30T21:40:20Z");
    assertThat(zonedDateTime, is(ZonedDateTime.of(2014, Month.AUGUST.getValue(), 30, 21, 40, 20, 0, ZoneId.of("Z"))));
  }

  /**
   * Date/time classes provide getter methods for obtaining their component values (different component resolutions).
   */
  @Test
  public void testGetDateTimeComponentValues() {
    final Month month = Month.AUGUST;
    int dayOfMonth = 31;
    int seconds = 59;

    final LocalDateTime localDateTime = LocalDateTime.of(2014, month, dayOfMonth, 18, 46, seconds);

    assertThat(localDateTime.getMonth(), is(month));
    assertThat(localDateTime.getDayOfMonth(), is(dayOfMonth));
    assertThat(localDateTime.getSecond(), is(seconds));
  }

  /**
   * Date/time classes are immutable. Therefore methods to alter instances of them are named with() rather than being
   * setters, and they return new instances.
   */
  @Test
  public void testAlterDateTimeComponentValues() {
    final LocalDateTime localDateTime = LocalDateTime.of(2014, Month.AUGUST, 30, 19, 02, 58);

    // Test altering component fields with literal values using withXXX()
    int pastYear = 2013;
    int pastDayOfMonth = 1;
    final LocalDateTime pastDateTime = localDateTime.withYear(pastYear).withDayOfMonth(pastDayOfMonth);
    // Construct separate LocalDate and Time from supplied component values, and time component of existing DateTime
    LocalDate expectedDate = LocalDate.of(pastYear, localDateTime.getMonth(), pastDayOfMonth);
    final LocalTime expectedTime = localDateTime.toLocalTime();
    // A LocalDateTime can be constructed from separate LocalDate and LocalTime
    assertThat(pastDateTime, is(LocalDateTime.of(expectedDate, expectedTime)));

    // Test altering component fields using delta method plusXXX()
    LocalDateTime futureDateTime = localDateTime.plusWeeks(3);
    expectedDate = LocalDate.of(localDateTime.getYear(), Month.SEPTEMBER, 20);
    assertThat(futureDateTime, is(LocalDateTime.of(expectedDate, expectedTime)));
    // Test altering component fields using generic delta method plus(value, Unit)
    futureDateTime = futureDateTime.plus(1, ChronoUnit.WEEKS);
    expectedDate = LocalDate.of(localDateTime.getYear(), Month.SEPTEMBER, 27);
    assertThat(futureDateTime, is(LocalDateTime.of(expectedDate, expectedTime)));
  }

  /**
   * The API supports truncating a Date, Time and DateTime to different precisions. Truncation results in the fields
   * with precisions smaller than the specified unit being set to zero.
   */
  @Test
  public void testTruncationTo() {
    final LocalDateTime localDateTime = LocalDateTime.of(2014, Month.SEPTEMBER, 1, 15, 56, 52, 1);
    // Note - To set seconds and nanoseconds to zero, you truncate the minutes.
    LocalDateTime truncatedDateTime = localDateTime.truncatedTo(ChronoUnit.MINUTES);
    assertThat(truncatedDateTime, is(LocalDateTime.parse("2014-09-01T15:56:00")));
  }

  /**
   * Illustrates how a zoned date/time can be created using a {@link ZoneId} to specify the time zone region.
   * <p>
   * The following is a paraphrased from the javadoc for {@link java.time.ZoneId}. A ZoneId is an identifier for a
   * time-zone region.
   * <p>
   * Logically there are two main types of time zone IDs: <br>
   *
   * 1) Fixed offset - A literal, hard-coded offset from UTC/GMT usually in terms of hours and/or mins. These zone IDs
   * are more typically represented using a {@link java.time.ZoneOffset}. <br>
   *
   * 2) Region-based IDs - An identifier for a time zone based used for a particular geographic region. These IDs are
   * configured via a ZoneRulesProvider. The most commonly used representation of time zone region identifiers are
   * defined in the IANA Time Zone Database (TZDB) and are strings in the format "Area/Region", e.g. "Europe/London" or
   * "America/New_York".
   */
  @Test
  public void testZoneIdRegionAndFixedOffset() {
    // Create zoned date/time using ZoneId to parse an IANA area/region format TZ ID (use one that doesn't vary with
    // daylight saving to ensure this test-case is stable)
    final ZoneId zoneId = ZoneId.of("Africa/Addis_Ababa");
    final ZonedDateTime zonedDateTime = ZonedDateTime.of(2014, Month.AUGUST.getValue(), 30, 21, 40, 20, 0, zoneId);

    // Use ZoneOffset to return the fixed offset of a zoned date/time from UTC
    final ZoneOffset zoneOffset = zonedDateTime.getOffset();
    int threeHoursInSeconds = 3 * 60 * 60;
    assertThat(zoneOffset.getTotalSeconds(), is(threeHoursInSeconds));
  }

  /**
   * You can modify the values of dates (only) using {@link java.time.Period}.
   * <p>
   * A {@link java.time.Period} models a length of time in terms of years, months and days. It’s a ‘distance’ in a
   * timeline, as opposed to other classes (above) being a point on a timeline.
   */
  @Test
  public void testPeriodToAlterDate() {
    // 3 years, 2 months, 1 day
    final Period period = Period.of(3, 2, 1);
    // Components of a Period are represented by ChronoUnit values
    assertThat(period.get(ChronoUnit.DAYS), is(1L));

    // You can modify the values of a Date using a Period
    final LocalDate localDate = LocalDate.of(2014, Month.SEPTEMBER, 1);
    final LocalDate futureDate = localDate.plus(period);
    assertThat(futureDate, is(LocalDate.of(2017, Month.NOVEMBER, 2)));
    // You can also use a Period to calculate the difference between two dates
    assertThat(Period.between(localDate, futureDate), is(period));

    final LocalDate pastDate = localDate.minus(period);
    assertThat(pastDate, is(LocalDate.of(2011, Month.JUNE, 30)));
  }

  /**
   * You can modify the values of times (only) using {@link java.time.Duration}.
   * <p>
   * A {@link java.time.Duration} serves a similar purpose to {@link java.time.Period} except that it models a length of
   * time in terms of seconds and nanoseconds.
   */
  @Test
  public void testDurationToAlterTime() {
    // A duration of 3 seconds and 5 nanoseconds
    Duration duration = Duration.ofSeconds(3, 5);

    // You can modify the values of a DateTime using a Duration
    final LocalDateTime localDateTime = LocalDateTime.of(2014, Month.SEPTEMBER, 1, 17, 29, 40);
    final LocalDateTime futureDateTime = localDateTime.plus(duration);
    assertThat(futureDateTime, is(LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.of(17, 29, 43, 5))));
    // You can also use a Duration to calculate the difference between two times
    assertThat(Duration.between(localDateTime, futureDateTime), is(duration));
  }

  /**
   * {@link java.time.MonthDay} is a holder for an associated month and day, such as a birthday.
   */
  @Test
  public void testMonthDayHolder() {
    final MonthDay birthday = MonthDay.of(Month.SEPTEMBER, 1);
    final LocalDate localDate = LocalDate.of(2014, birthday.getMonthValue(), birthday.getDayOfMonth());

    assertThat(localDate.getMonth(), is(birthday.getMonth()));
  }

  /**
   * {@link java.time.YearMonth} is a holder for an associated year and month, such as that used for expiry dates.
   */
  @Test
  public void testYearMonthHolder() {
    final YearMonth expiry = YearMonth.of(2014, Month.SEPTEMBER);
    final LocalDate localDate = LocalDate.of(expiry.getYear(), expiry.getMonthValue(), 1);

    assertThat(localDate.getMonth(), is(expiry.getMonth()));
  }

  /**
   * Provides an example of using the new {@link java.time.Clock} class' {@link Clock#fixed(Instant, ZoneId)} method to
   * obtain a clock that always returns the same instant (current date/time).
   * <p>
   * The date/time API includes a new abstract class {@link java.time.Clock} which can be used to find the current
   * date/time (instant) for an identified time-zone. This duplicates a capability of the new date/time classes which
   * provide a now() factory method, and, for discovery of the current time in UTC, the traditional use of
   * {@link System#currentTimeMillis()}. However, Clock, is primarily intended to provide an injectable (non-static)
   * means of deriving the current time, to support and simplify testing of time sensitive code.
   *
   * @throws Exception If an unexpected error occurs.
   */
  @Test
  public void testClockFixed() throws Exception {
    // A clock which always returns a fixed date/time - in this case 'now', in UTC
    Clock clock = Clock.fixed(Instant.now(), ZoneId.of("UTC"));

    Instant instant1 = clock.instant();
    Thread.sleep(1);
    Instant instant2 = clock.instant();

    assertThat(instant2, is(instant1));
  }

  /**
   * Provides an example of using the new {@link java.time.Clock} class' {@link Clock#offset(Clock, Duration)} method to
   * obtain a clock that returns an instant which is always a specified duration before or after the current date/time.
   * <p>
   * For further explanation of the {@link java.time.Clock} class, see {@link #testClockFixed()}.
   *
   * @throws Exception If an unexpected error occurs.
   */
  @Test
  public void testClockOffset() throws Exception {
    // A clock with a date/time which is always 1 hour behind the current system date/time, in UTC
    Clock clock = Clock.offset(Clock.systemUTC(), Duration.ofHours(-1));

    Thread.sleep(1);
    long currentTimeMillis = Instant.now().toEpochMilli();
   
    // The offset clock should return a date/time, behind the current date/time
    assertThat(clock.instant().toEpochMilli(), lessThan(currentTimeMillis));
  }
}
TOP

Related Classes of com.neiljbrown.examples.java8.DateTimeExamplesTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.