Chapter 4

Working with Dates and Times

IN THIS CHAPTER

check Understanding human and computer dates and times

check Using java.time classes to represent dates and times

check Comparing dates and times

check Performing calculations with dates and times

check Formatting dates and times

Does anybody really know what time it is? Does anybody really care about time?

So mused Robert Lamm of The Chicago Transit Authority (later known as simply Chicago) in 1969.

I’m not sure who cared much about time in 1969, but I do know that the people who designed the original version of Java in 1995 didn’t care much about it, at least as evidenced by the weak classes they provided for working with times and dates in the Java.util package. Java programmers have long struggled with simple calculations involving dates and times, such as determining what the date will be 45 days from today or calculating the number of days between two given dates.

Java finally got with the times with the release of Java 8, which introduced an entirely new framework for working with dates and times, usually referred to as the Date-Time API. This new API is pretty complicated, involving about 50 new classes and interfaces and hundreds of new methods. In this chapter, I’ll introduce you to just a few of the most important and useful classes of the new Date-Time API. Then you can explore the rest online via Oracle’s documentation at http://download.java.net/jdk9/docs/api/index.html.

Pondering How Time is Represented

Before I launch into the details of the new Date-Time API’s classes, let’s review a few basic concepts about time. Probably the most important basic concept to understand about time (at least from a programming point of view) is that computers and humans use two entirely different methods of keeping track of time. Humans measure time using a system of progressively longer units, starting with seconds and increasing to minutes, hours, days, weeks, months, years, decades, and centuries.

Our human time units are intuitively familiar to us, but their precise definitions are more complicated than you might guess. All kinds of factors muck up the way we represent time: leap days, time zones, and daylight-saving time. And did you know that about once every 18 months, scientists pick a day (they usually choose June 30 or December 31) that they add one second to? This is necessary because the speed of the earth’s rotation varies ever so slightly, throwing our clocks off.

In contrast, the way computers keep track of time is much simpler: Computers simply count the number of units (typically milliseconds or nanoseconds) that have elapsed since a given start time. Thus, to a computer, a time is just a number.

In Java, machine time is set as the number of nanoseconds that have elapsed since midnight, January 1, 1970. Why January 1, 1970? There’s no particular reason other than historical: Java inherited that date from the Unix operating system, which was developed in the 1970s. (For more information, see the sidebar “And you thought Y2K was bad!”)

tip The designers of Microsoft Windows decided to use January 1, 1601 as the start day for their clock. I guess that was a big year for William Shakespeare; in 1601 he was able to use the first version of Microsoft Word to write his plays.

The difference between how humans and computers keep track of time makes any computer program that deals with dates and times a bit tricky. For example, suppose you want to schedule a phone call between two people, one in Los Angeles, the other in New York. Obviously, the time that you agree upon for the call must take into account the time zone of each participant. Thus you might agree to make the call at 1 p.m. local time for the West Coast participant and 4 p.m. local time for the East Coast participant. So, how would you represent that appointment time in a database?

Or suppose you want to calculate the due date for an invoice that is dated January 27, 2015, when the payment due date is 45 days after the invoice date. The algorithm that calculates the due date must be aware that January has 31 days and that February has 28 days in 2015.

Fortunately, the new Date-Time API is designed to handle all those nuances for you. The Date-Time API includes all the classes you need to represent dates and times in just about any imaginable context, for performing calculations and comparisons between date and time objects, and for converting dates and times to string representations in just about any imaginable format.

Picking the Right Date and Time Class for Your Application

The first order of business when developing an application that must work with dates or times (or both) is picking the Date-Time class to represent your date and time values. The java.time package defines ten distinct classes used to represent different types of times and dates, as described in Table 4-1.

TABLE 4-1 Ten Date-Time Classes in java.time

Class

What It Represents

LocalTime

A time (hours, minutes, and seconds to nanosecond precision) without an associated time zone.

LocalDate

A date (year, month, and day) without an associated time zone.

LocalDateTime

A date and time without an associated time zone.

OffsetTime

A time and an offset from UTC (Coordinated Universal Time, also known as Greenwich Mean Time), such as 12:30:00-8.00, which means the time is 12:30 with an offset of -8 hours from UTC.

OffsetDateTime

A date and time with an offset value from UTC.

ZonedDateTime

A date and time with an associated time zone, such as America/Los_Angeles.

MonthDay

A month and day without an associated year. You can use a MonthDay object to represent a date such as a birthday, anniversary, or holiday.

YearMonth

A year and month, such as December, 2015. No day, time, or time zone values are associated with the year and month.

Year

A year, such as 2038. No month, day, time, or time zone values are associated with the year.

Instant

A single point of time, represented internally as the number of nanoseconds that have elapsed since midnight, January 1, 1970. The value assumes a UTC/GMT time offset of 0.

Each of these classes has many different methods that let you create date and time objects, perform calculations on them, compare them, and convert them to strings that can be displayed and read by humans. You can find complete documentation of the methods for each of these classes online at http://download.java.net/jdk9/docs/api/index.html.

Using the now Method to Create a Date-Time Object

All Date-Time classes have a static now method, which creates an object representing the current date and/or time. For example, to get the current date, you would use code similar to this:

LocalDate date = LocalDate.now();

To get the current date and time with time zone, use this code:

ZonedDateTime datetime = ZonedDateTime.now();

The following program displays the current time using all ten classes, creating an object of each class using now() and printing it with toString():

import java.util.*;
import java.time.*;

public class TimeTester
{
public static void main(String[] args)
{
System.out.println(" LocalTime: "
+ LocalTime.now().toString());
System.out.println(" LocalDateTime: "
+ LocalDateTime.now().toString());
System.out.println(" ZonedDateTime: "
+ ZonedDateTime.now().toString());
System.out.println(" OffsetTime: "
+ OffsetTime.now().toString());
System.out.println(" OffsetDateTime: "
+ OffsetDateTime.now().toString());
System.out.println(" MonthDay: "
+ MonthDay.now().toString());
System.out.println(" YearMonth: "
+ YearMonth.now().toString());
System.out.println(" Instant: "
+ Instant.now().toString());
}
}

If you compile and run this program, the output will appear something like this:

LocalTime: 20:56:26.325

LocalDateTime: 2013-10-07T20:56:26.388

ZonedDateTime: 2013-10-07T20:56:26.388-07:00[America/Los_Angeles]

OffsetTime: 20:56:26.388-07:00

OffsetDateTime: 2013-10-07T20:56:26.388-07:00

MonthDay: --10-07

YearMonth: 2013-10

Instant: 2013-10-08T03:56:26.388Z

From this output, you can get an idea of the information represented by the various Date-Time classes.

Using the parse Method to Create a Date-Time Object

Another way to create a Date-Time object is to use the static parse method, which creates a Date-Time object from a string that represents a specific date or time. For example, the following code creates a LocalDate object representing December 15, 2014:

LocalDate d = LocalDate.parse("2014-12-15");

To create a LocalDateTime object that represents a specific time on a specific date, use the parse method. Here’s an example that sets the time to 3:45 p.m. on December 15, 2014:

LocalDateTime dt;
dt = LocalDateTime.parse("2014-12-15T15:45");

Note that the letter T separates the date from the time, and the time is expressed in 24-hour clock format. If you need to be more precise, you can also specify seconds, as in this example:

dt = LocalDateTime.parse("2014-12-15T15:45:13.5");

Here the time is set to 13.5 seconds after 2:45 p.m.

If the string is not in the correct format, the parse method throws a DateTimeParseException. Whenever you use the parse method, you should enclose it in a try block and catch this exception, as in this example:

LocalDateTime dt;
try
{
dt = LocalDateTime.parse("2014-12-15T03:45PM");
}
catch (DateTimeParseException ex)
{
System.out.println(ex.toString());
}

The parse method is especially useful for converting user input to a Date-Time object. For example, you might use it along with the Scanner class to read a date from the console, or you can use parse in a Swing application to read a date from a text box. When you do, you should prompt the user with the expected date format and catch DateTimeParseException in case the user enters the date in the wrong format.

Using the of Method to Create a Date-Time Object

A third way to create Date-Time objects is to use the static of method to create a Date-Time object from its constituent parts. For example, you can create a LocalDate object by supplying integers that represent the year, month, and day like this:

LocalDate date = LocalDate.of(2014,12,15);

Each of the Date-Time classes has one or more variations of the of method, as spelled out in Table 4-2.

TABLE 4-2 Date-Time of Methods

Class

Method

LocalTime

of(int hour, int minute)

of(int hour, int minute, int second)

of(int hour, int minute, int second, int nanoOfSecond)

LocalDate

of(int year, int month, int dayOfMonth)

of(int year, Month month, int dayOfMonth)

LocalDateTime

of(int year, int month, int dayOfMonth, int hour, int minute)

of(int year, int month, int dayOfMonth, int hour, int minute, int second)

of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond)

of(int year, Month month, int dayOfMonth, int hour, int minute)

of(int year, Month month, int dayOfMonth, int hour, int minute, int second)

of(int year, Month month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond)

of(LocalDate date, LocalTime time)

OffsetTime

of(int hour, int minute, int second, int nanoOfSecond, ZoneOffset offset)

of(LocalTime time, ZoneOffset offset)

OffsetDateTime

of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond, ZoneOffset offset)

of(LocalDate date, LocalTime time, ZoneOffset offset)

of(LocalDateTime dateTime, ZoneOffset offset)

MonthDay

of(int month, int dayOfMonth)

of(Month month, int dayOfMonth)

YearMonth

of(int year, int month)

of(int year, Month month)

Year

of(int year)

Note that several of the methods in Table 4-2 use the additional types Month, ZoneOffset, and ZoneId. These types are described in the following sections.

Using the Month enumeration

Several of the methods listed in Table 4-2 let you specify the month as a Month object. Month is an enumeration that represents the twelve months of the year, as follows:

Month.JANUARY

Month.MAY

Month.SEPTEMBER

Month.FEBRUARY

Month.JUNE

Month.OCTOBER

Month.MARCH

Month.JULY

Month.NOVEMBER

Month.APRIL

Month.AUGUST

Month.DECEMBER

Thus you can create a date like this:

LocalDate date = LocalDate.of(2014,Month.DECEMBER,15);

Interestingly, the Month enumeration has some interesting methods which you might find occasionally useful. For example, you can print the number of days in December like this:

System.out.println("December hath "
+ Month.DECEMBER.length(false) + " days.");

The boolean argument in the length method indicates whether the calculation should be for a leap year. Consult the online documentation for other useful methods of the Month enumeration.

Using the ZoneId class

To create a ZonedDateTime, you must first create a time zone object by using the ZoneId class. To create a time zone, you must know the standard name of the time zone you want to create. Unfortunately, there are more than 500 distinct zone IDs, and they periodically change. So listing them here would be impractical, but you can easily list them all by using this handy bit of code:

for (String id : ZoneId.getAvailableZoneIds())
System.out.println(id);

This for loop will write the names of each ZoneId to the console.

Once you know the name of the ZoneId you want to use, you can create it using ZoneId.of , then use it to create a ZonedDateTime as in this example:

ZoneId z = ZoneId.of("America/Los_Angeles");
ZonedDateTime zdate;
zdate = ZonedDateTime.of(2014, 12, 15, 0, 0, 0, 0, z);

Or, if you prefer, you can create the ZoneId directly when you create the ZonedDateTime:

zdate = ZonedDateTime.of(2014, 12, 15, 0, 0, 0, 0,
ZoneId.of("America/Los_Angeles"));

Using the ZoneOffset class

The of method OffsetTime and OffsetDateTime classes use an additional class named ZoneOffset to indicate the offset from UTC. You can create a ZoneOffset by using any of the following methods of the ZoneOffset class:

  • of(String offsetId)
  • ofHours(int hours)
  • ofHoursMinutes(int hours, int minutes)
  • ofHoursMinutesSeconds(int hours, int minutes, int seconds)
  • ofTotalSeconds(int totalSeconds)

For example, you can create a ZoneOffset of -8 hours like this:

ZoneOffset z = ZoneOffset.ofHours(-8);

Alternatively, you could specify the offset as a string, as in this example:

ZoneOffset z = ZoneOffset.of("-08:00");

Note that when you use a string offset, you must provide two digits for the hours, minutes, and (optionally) seconds.

Once you have a ZoneOffset object, you can use it to create an OffsetTime, as in this example:

OffsetTime time = OffsetTime.of(10, 30, 0, 0, z);

Or if you prefer, you can create the ZoneOffset directly in the call to the OffsetTime’s of method:

OffsetTime time = OffsetTime.of(10, 30, 0, 0,
ZoneOffset.ofHours(-8));

Looking Closer at the LocalDate Class

The basic java.time classes are similar enough that once you learn how to use one of them, you’ll find it easy to learn how to use the rest. Thus, for the rest of this chapter, I’ll focus on just one: the LocalDate class. This class represents a date (year, month, and day) without an associated time. In this section and in the sections that follow, you’ll learn how to use many of the methods of this class to extract information about a date, to compare two dates, and to perform calculations on a date.

Table 4-3 shows the most commonly used methods of the LocalDate class. For your convenience, this table includes the methods used to create LocalDate objects, even though those methods have already been covered earlier in this chapter.

TABLE 4-3 Methods of the LocalDate Class

Method

Explanation

Methods that create a LocalDate object

LocalDate now()

Creates a LocalDate object that represents the current date.

LocalDate of(int year, int month, int dayOfMonth)

Creates a LocalDate object with a given year, month, and day.

LocalDate of(int year, Month month, int dayOfMonth)

Creates a LocalDate object with a given year, month, and day.

LocalDate parse(String text)

Creates a LocalDate object by parsing the text string.

Methods that extract information about a date

int getYear()

Returns the year.

Month getMonth()

Returns the month as a Month object.

int getMonthValue()

Returns the month as an int from 1 through 12.

int getDayOfMonth()

Returns the day of the month.

DayOfWeek getDayOfWeek()

Returns the day of the week as a DayOfWeek object.

int getDayOfYear()

Returns the day of the year.

int lengthOfMonth()

Returns the number of days in this month.

int lengthOfYear()

Returns the number of days in this year.

Methods that compare dates

boolean isAfter(LocalDate other)

Returns true if other occurs after this date.

boolean isBefore(LocalDate other)

Returns true if other occurs after this date.

boolean isEqual(LocalDate other)

Returns true if this date and other represent the same date.

Methods that perform date calculations

LocalDate plusDays(long days)

Returns a copy of the LocalDate with the specified number of days added.

LocalDate plusNMonths(long days)

Returns a copy of the LocalDate with the specified number of months added.

LocalDate plusWeeks(long months)

Returns a copy of the LocalDate with the specified number of weeks added.

LocalDate plusYears(long days)

Returns a copy of the LocalDate with the specified number of years added.

LocalDate minusDays(long days)

Returns a copy of the LocalDate with the specified number of days subtracted.

LocalDate minusMonths(long months)

Returns a copy of the LocalDate with the specified number of months subtracted.

LocalDate minusWeeks(long months)

Returns a copy of the LocalDate with the specified number of weeks subtracted.

LocalDate minusYears(long years)

Returns a copy of the LocalDate with the specified number of years subtracted.

long until(LocalDate endDate, ChronoUnit unit)

Returns the difference between this date and the specified date measured in the specified units.

Extracting Information About a Date

Several methods of the LocalDate class let you extract useful information about a given date. For instance, the following example shows how you can extract the current year, month, and day:

LocalDate date = LocalDate.now();
int year = date.getYear();
int month = date.getMonthValue();
int day = date.getDayOfMonth();

If you need to know how many days into the year a particular date is, you can use this code:

LocalDate date = LocalDate.parse("2016-04-09");
System.out.println(date.getDayOfYear());

This example will print the number 100, as April 9 is the 100th day of 2016.

The getDayOfWeek method returns a value of type DayOfWeek, which is an enumeration with the following values:

SUNDAY

THURSDAY

MONDAY

FRIDAY

TUESDAY

SATURDAY

WEDNESDAY

Here’s an example of how you might use this method:

LocalDate date = LocalDate.parse("2016-04-09");
System.out.println(date.getDayOfWeek());

In this example, the string SATURDAY will be printed because in 2016, April 9 falls on a Saturday.

The lengthOfMonth and lengthOfYear are useful if you want to know the number of days in the month or year represented by a LocalDate. Both methods take into account leap years.

Comparing Dates

You can’t compare Date-Time objects using Java’s standard comparison operators. Consider the following example:

if (LocalDate.now() == LocalDate.now())
System.out.println("All is right in the universe.");
else
System.out.println("There must be a disturbance " +
"in the space-time continuum!");

If you run this code, There must be a disturbance in the space-time continuum! will be printed. That’s because when used on objects, the equality operator tests whether two expressions refer to the same object, not to objects with the same value.

To test the equality of two dates, you must use the isEqual method, as in this example:

if (LocalDate.now().isEqual(LocalDate.now()))
System.out.println("All is right in the universe.");

Similarly, you must use either the isBefore or the isAfter method to determine whether one date falls before or after another date.

Note that you can use built-in operators with methods that return integer results. Thus, the following code will work just as you would expect:

if (LocalDate.now().getDayOfMonth() < 15)
System.out.println("It is not yet the 15th.");

Because the getDayOfMonth method returns an integer, you can use the < operator to determine if the 15th of the month has yet arrived.

Calculating with Dates

Just as you cannot use Java’s built-in comparison operators with dates, you also may not use built-in mathematical operators. Instead, you can perform addition and subtraction on dates using the various plus and minus methods, and you can determine the difference between two dates by using the until method.

technicalstuff An important fact to consider when doing date and time calculations is that Date-Time objects are immutable. That means that once you create a Date-Time object, you cannot change its value. When you perform a calculation on a Date-Time object, the result is a new Date-Time object with a new value.

The plus and minus methods let you add various date and time units to a Date-Time object. Table 4-3 lists four variants of each for the LocalDate class, allowing you to add or subtract years, months, weeks, and days to a LocalDate object. The following code prints the current date, tomorrow’s date, and the date one week, one month, and one year from now:

System.out.println("Today: " + LocalDate.now());
System.out.println("Tomorrow: " + LocalDate.now().plusDays(1));
System.out.println("Next week: " + LocalDate.now().plusWeeks(1));
System.out.println("Next month: " + LocalDate.now().plusMonths(1));
System.out.println("Next year: " + LocalDate.now().plusYears(1));

tip To determine the difference between two dates, use the until method. It calculates the difference between a date and the date passed as the first parameter, measured in the units indicated by the second parameter. For example, the following code determines the number of days between May 16, 2014 and December 15, 2014:

LocalDate date1 = LocalDate.parse("2014-05-16");
LocalDate date2 = LocalDate.parse("2014-12-15");
System.out.println(date1.until(date2, ChronoUnit.DAYS));

Some date calculations can be a bit more complex. For example, consider a business that prepares invoices on the 15th of each month. The following snippet of code displays the number of days from the current date until the next invoicing date:

LocalDate today = LocalDate.now();
LocalDate invDate = LocalDate.of(today.getYear(),
today.getMonthValue(), 15);
if (today.getDayOfMonth() > 15)
invDate = invDate.plusMonths(1);
long daysToInvoice = today.until(invDate,
ChronoUnit.DAYS);
System.out.println(daysToInvoice
+ " until next invoice date.");

This example works by first getting the current date, then creating a new LocalDate object that represents the 15th of the current month. Then, if the current day of the month is greater than 15, it adds one month to the invoicing date. In other words, if it is the 16th or later, invoicing occurs on the 15th of the following month, not of this month. Then it uses the until method to determine the number of days between the current date and the next invoicing date.

technicalstuff ChronoUnit is an enumeration that defines the various units of time that can be used in date and time calculations. The possible values are:

CENTURIES
DAYS
DECADES
ERAS
FOREVER
HALF-DAYS
HOURS
MICROS
MILLENNIA
MILLIS
MINUTES
MONTHS
NANOS
SECONDS
WEEKS
YEARS

Most of these are self-explanatory, but two of them are a bit peculiar:

  • ERA indicates whether the date refers to the Common Era (CE, also known as AD) or Before Era (BCE, also known as BC).
  • FOREVER represents the largest value that can be represented as a duration. Sadly, Java won’t let you live forever. The following code throws an exception:

    LocalDate birthday = LocalDate.parse("1959-05-16);
    birthday = birthday.plus(1,ChronoUnit.FOREVER);

Note that ChronoUnit is in the java.time.temporal package, so be sure to include the following statement at the top of any program that uses ChronoUnit:

import java.time.temporal.*;

Formatting Dates

If you use the toString() method to convert a LocalDate to a string, you get a string such as 2014-10-31. What if you want to display the date in a different format, such as 10-31-2014 or October 31, 2014? To accomplish that, you can use the format method of the LocalDate class along with a custom formatter you create using the DateTimeFormatter class. To specify the format you want to use, you pass the DateTimeFormatter class a pattern string, using the formatting symbols listed in Table 4-4.

TABLE 4-4 Formatting Characters for the DateTimeFormatter Class

Format pattern

Explanation

y

Year (two or four digits)

M

Month (one or two digits or three or more letters)

d

Day of month (such as 1, 28)

H

Hour

m

Minute

s

Second (0 to 59)

h

Clock hour (1 to 12)

a

AM or PM

V

Time zone ID (such as America/Los_Angeles)

z

Time zone name (such as Pacific Daylight Time)

The easiest way to create a DateTimeFormatter object is to use the static ofPattern method along with a pattern string. For example:

DateTimeFormatter formatter;
formatter = DateTimeFormatter.ofPattern("dd MMM YYYY");

This formatter produces dates formatted like 04 SEP 2014. You can then use the formatter to produce a formatted date string like this:

LocalDate date = LocalDate.now();
String formattedDate = date.format(formatter);

Here’s a simple program that prints the current date in several different formats:

import java.util.*;
import java.time.*;
import java.time.format.*;
public class FormatDateTime
{
public static void main(String[] args)
{
LocalDateTime now = LocalDateTime.now();
printDate(now, "YYYY-MM-dd");
printDate(now, "MM-dd-YYYY");
printDate(now, "dd MMM YYYY");
printDate(now, "MMMM d, YYYY");
printDate(now, "HH:mm");
printDate(now, "h:mm a");
}

public static void printDate(LocalDateTime date, String pattern)
{
DateTimeFormatter f;
f = DateTimeFormatter.ofPattern(pattern);
pattern = (pattern + " ").substring(0, 14);
System.out.println(pattern + " " + date.format(f));
}
}

When you run this program, you’ll get console output that resembles this:

YYYY-MM-dd 2013-10-09
MM-dd-YYYY 10-09-2013
dd MMM YYYY 09 Oct 2013
MMMM d, YYYY October 9, 2013
HH:mm 20:29
h:mm a 8:29 PM

technicalstuff Did you notice the cool formatting trick I used? I forced the System.out.println() patterns to print 14-character-long strings so all the dates would line up. The padding is accomplished by this slick line of code:

pattern = (pattern + " ").substring(0, 14);

Here a string of 14 spaces is added to the pattern string, then a 14-character-long substring is taken starting at the first character. I figured the nice spacing in the output would make it easier for you to see the effect of each of the pattern strings.

Looking at a Fun Birthday Calculator

Now that you’ve seen the techniques for working with Date-Time objects, it’s time to look at a complete programming example. Listing 4-1 presents a program that prompts the user to enter his or her birthday and then prints a variety of interesting information deduced from the date, including:

  • The day of the week on which the user was born
  • The user’s age in years
  • The date of the user’s next birthday
  • The number of days until the user’s next birthday
  • The user’s half-birthday (six months from his or her birthday)

Here’s an example of the BirthdayFun application in action:

Today is October 9, 2013.

Please enter your birthdate (yyyy-mm-dd): 1959-12-15

December 15, 1959 was a very good day!
You were born on a TUESDAY.
You are 53 years young.
Your next birthday is December 15, 2013.
That's just 67 days from now!
Your half-birthday is June 15.

Another? (Y or N) N

LISTING 4-1 The BirthdayFun Application

import java.util.*;
import java.time.*; →2
import java.time.format.*;
import java.time.temporal.*;

public class BirthdayFun
{
static Scanner sc = new Scanner(System.in); →8

public static void main(String[] args)
{
do
{
LocalDate birthDate; →14

DateTimeFormatter fullFormat = →16
DateTimeFormatter.ofPattern("MMMM d, YYYY");
DateTimeFormatter monthDayFormat =
DateTimeFormatter.ofPattern("MMMM d");

System.out.println("Today is " →21
+ LocalDate.now().format(fullFormat) + ".");

System.out.println();
System.out.print("Please enter your birthdate "
+ "(yyyy-mm-dd): ");
String input = sc.nextLine();
try
{
birthDate = LocalDate.parse(input); →30

if (birthDate.isAfter(LocalDate.now())) →32
{
System.out.println("You haven't been born yet!");
continue;
}
System.out.println();
System.out.println(birthDate.format(fullFormat) →40

+ " was a very good day!");
DayOfWeek birthDayOfWeek = birthDate.getDayOfWeek(); →42

System.out.println("You were born on a "
+ birthDayOfWeek + ".");
long years = birthDate.until(LocalDate.now(), →46

ChronoUnit.YEARS);
System.out.println("You are " + years + " years young.");
LocalDate nextBDay = birthDate.plusYears(years + 1); →50

System.out.println("Your next birthday is "
+ nextBDay.format(fullFormat) + ".");
long wait = LocalDate.now().until(nextBDay, →54

ChronoUnit.DAYS);
System.out.println("That's just " + wait
+ " days from now!");
LocalDate halfBirthday = birthDate.plusMonths(6); →59
System.out.println("Your half-birthday is "
+ halfBirthday.format(monthDayFormat) + ".");
}
catch (DateTimeParseException ex)
{
System.out.println("Sorry, that is not a valid date.");
}
} while(askAgain());
}

private static boolean askAgain()
{
System.out.println();
System.out.print("Another? (Y or N) ");
String reply = sc.nextLine();
if (reply.equalsIgnoreCase("Y"))
{
return true;
}
return false;
}
}

The following paragraphs explain the most important lines in this program:

  1. →2 The program uses classes from three packages: java.time, java.time.format, and java.time.temporal.
  2. →8 A Scanner is used to get the user input. The Scanner is defined as a class variable so that it can be accessed by both the main and the askAgain methods.
  3. →14 The birthdate variable is used to store the birthdate entered by the user.
  4. →16 The program uses two formatters: fullFormat formats the date in full-text format (such as December 15, 1959) and monthDay Format formats the date as just a month and day.
  5. →21 This line displays the current date.
  6. →21 This line displays the current date.
  7. →31 The string entered by the user is parsed.
  8. →32 The if statement ensures that the user has not entered a date in the future.
  9. →40 The date entered by the user is displayed.
  10. →42 The day of the week is calculated and displayed.
  11. →46 The person’s age is calculated by determining the difference between the current date and the birthdate in years.
  12. →50 The date of the person’s next birthday is calculated by adding the person’s age plus 1 year to the original birthdate.
  13. →54 The number of days until the person’s next birthday is calculated.
  14. →59 The person’s half birthday is calculated by adding six months to the original birthdate.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset