Since Java 8, the java.util.Date class is deprecated and new package java.time was introduced. Even though the old Date class is still usable and you can find it in legacy project, it’s much advised to use the new package which corrected some lacks from old class.
For certification and interview exam, you should of course learn the new package. This article will be separated in two parts, a first one with more basic knowledge that’ll be useful to pass the OCA (Associate / programmer level 1) certification, a second part aimed at OCP (Professional / level 2) certification, which requires more knowledge of the time package (additional classes).
Even if studying for OCP, you definitely have to start with the basic knowledge and understand it well.
This series of articles are meant for people who already know the basics of Java, that is grammar and vocabulary, and knowledge of OOP. The topics covered correspond to OCA Programmer I level and relate to Java 8 version. If you need to learn the basics, I can recommend the JetBrains Academy Java developer track.
Java Time Package – OCA topics (basics)
The java.time package contains a few classes, you might already the most used ones: LocalDate, LocalTime and LocalDateTime.
Creating a date or time object in Java
These three make immutable objects, use static methods for object creation (their constructors are private) -that’s the case for most, if not all, classes of the time package-.
Here are ways to create dates, times and timestamps:
- any class .now() returns the current date/time/date-time
- LocalDate.of(year, month, day); /* month can be represented with the number of the month or using the Enum Month.MONTH_NAME */
- LocalTime.of(hours, minutes, seconds, nanoseconds); // last parameter is optional
- LocalDateTime.of(year, month, day, hour, minutes, seconds);
- LocalDateTime.of(date, time);
I’d advise you to go check the full list of static creation methods in the official documentation and at least read carefully the whole list of methods.
In the certification exam, you could encounter methods that you didn’t study, because their name is thought to be self-speaking enough, or because they would give you a quick explanation on what it does and how. But always better to be too prepared than losing time wondering things.
These classes can throw a DateTimeException.
Date and Time methods
There’s list of methods to add a time period to your date/time object. They are called like .plusYears(int), .plusMinutes(int)… and so on. They do return an object of type LocalDate/LocalTime/LocalDateTime according to the object they’re applied too. Equivalent methods exist with “minus”.
The trick with those methods is that if you chain them and assign the return to a variable, only the last one is actually executed! That’s a recurrent exam question.
The methods .isBefore()/.isAfter() speak for themselves.
The methods .getDayOfWeek(), .getMonth(), .getHour() return an int except the getMonth() method that returns an Enum of type Month. They have to be applied on the right type of object. For example, getHour() on a LocalDate object, it would not compile.
Instant, Duration, Period
Period and Duration express duration of date or time, and have to be used with the right objects. Period expresses an amount of time in units (years, days…) and Durations an amount in nano-seconds.
- Period.of(years, months, days); // only available signature for .of()
They can be passed as parameter of LocalDate/Time/DateTime which accept an argument of type TemporalAmount (interface implemented by Period and Duration), like methods .plus(TemporalAmount) or .minus(TemporalAmount).
Period p = Period.between(firstDate, secondDate); Duration d = Duration.ofHours(2); long d1 = d.minusMinutes(15).getSeconds(); int d2 = d.getNano(); int p1 = p.getDays(); boolean isNegative = p.isNegative();
Instants represent an instantaneous point on the time-line (a “moment”);
Instant i = Instant.now(); int epoch = i.getNano(); // since 1/1/1970, epoch time
Instant.now() represents a moment in UTC while LocalDateTime.now() represents a date-time without zone and offset. I find that particular point hard to understand as LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()); prints the same as LocalDateTime.now();, so I’ll leave that link on StackOverflow about the difference between LocalDateTime and Instant.
Date and Time formatting and parsing
DateTimeFormatter comes in the java.time.format package. There are standard formats defined by java in java.time.format.FormatTime but you can also define custom formats.
Examples of use:
- String formatted = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
- DateTimeFormatter format = DateTimeFormatter.ofLocalizedDate(formatStyle); // FormatStyle is an Enum which contains LONG, SHORT, MEDIUM, FULL values
- DateTimeFormatter format = DateTimeFormatter.ofLocalizedDate(formatStyle).localizedBy(locale);
- DateTimeFormatter.ofPattern(“MMMM, dd, yyyy, hh:mm”);
- DateTimeFormatter.ofPattern(“EEEE dd MM yyyy”, locale); // that custom format = FormatStyle.MEDIUM, outputs for example “Monday 01 Apr 2020”
Capital Ms represent the month, like:
- M would print 1
- MM would print 01
- MMM would print JAN
- MMMM would print JANUARY
Lower y is the year:
- yy = 21
- yyyy = 2021
Lower h is for hours:
- h = 7
- h = 07
Finally, you can create a LocalDate/Time/DateTime from a String with the static .parse(“…”) method, which takes an optional DateTimeFormatter as second parameter. Unreadable format would throw an exception.
ZonedDateTime holds a LocalDateTime, a ZoneId and a ZoneOffset. It has the same time management capabilities as LocalDateTime, plus time zone specific operations. It accounts for daylight saving time and timezone differences.
ZoneId london = ZoneId.of("Europe/London"); LocalDateTime time = LocalDateTime.now(); ZonedDateTime londonTime = ZonedDateTime.of(time, london); // What time is it in L.A. when it's ... in London time? ZonedDateTime laTime = londonTime.withZoneSameInstant(ZoneId.of("America/Los_Angeles"); // pay attention this is an instance method
Timezone can be set in different ways:
ZoneId.of("America/Los_Angeles"); ZoneId.of("GMT+2"); ZoneId.of("UTC - 05:00"); ZoneId.systemDefault();
Locale is an OCP topic. Locale represents a specific geographical, political, or cultural region. It’s part of the java.util package.
Locale loc = new Locale("en", "GB"); = new Locale("en", "GB", "EURO"); = new Locale("fr", "029"); = new Locale("fr"); // instantiated by constructors! Locale current = Locale.getDefault(); // static // language tag allows constructing locales for various calendars, numbering systems, currencies... Locale.forLanguageTag("th-TH-u-ca-buddhist-nu-thai");
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(locale); // other methods exist such as getPercentInstance, getNumberInstance... String formattedPrice = currencyFormat.format(50.20); // 50.20 € for example, according to Locale used BigDecimal price =(BigDecimal) currentFormat.parse("£1.75"); // 1.75 Double tax = (Double) percentFormat.parse("12%"); // 0.12 int qty = numberFormat.parse("54,321").intValue(); // 54321
Note that in last example, the comma in the string is the number separator according to locale, not a floating point decimal separator.
ResourceBundle is part of the java.util package. It represents a collection of localizable key-value resources.
bundle.getString(key); // get value