JavaRush /Java Blog /Random EN /Java 8 Guide. Part 2.
Level 13

Java 8 Guide. Part 2.

Published in the Random EN group

Date API

Java 8 contains completely new date and time APIs in the java.time package. The new Date API is comparable to the Joda-Time library , however it is not the same. The following examples will cover the most important parts of the new API.
Clock gives access to the current date and time. Clocks are aware of time zones and can therefore be used instead of System.currentTimeMillis() to return the current time in milliseconds. This kind of time precision is also represented by the Instant class . Instants can be used to create inherited java.util.Date objects . Clock clock = Clock.systemDefaultZone(); long millis = clock.millis(); Instant instant = clock.instant(); Date legacyDate = Date.from(instant); // legacy java.util.Date
Timezones are represented by the abstract class ZoneId . They can be easily accessed using statistical factory methods. Timezones define offsets that are important for converting between instantaneous and local date and time. System.out.println(ZoneId.getAvailableZoneIds()); // prints all available timezone ids ZoneId zone1 = ZoneId.of("Europe/Berlin"); ZoneId zone2 = ZoneId.of("Brazil/East"); System.out.println(zone1.getRules()); System.out.println(zone2.getRules()); // ZoneRules[currentStandardOffset=+01:00] // ZoneRules[currentStandardOffset=-03:00]
LocalTime displays the time without a time zone, for example 17:30:15. The following example creates two local time objects for the time zones defined above. We then compare the two objects and calculate the difference in hours and minutes between them. LocalTime now1 =; LocalTime now2 =; System.out.println(now1.isBefore(now2)); // false long hoursBetween = ChronoUnit.HOURS.between(now1, now2); long minutesBetween = ChronoUnit.MINUTES.between(now1, now2); System.out.println(hoursBetween); // -3 System.out.println(minutesBetween); // -239 LocalTime comes with various factory methods to make instantiation easier, including string parsing. LocalTime late = LocalTime.of(23, 59, 59); System.out.println(late); // 23:59:59 DateTimeFormatter germanFormatter = DateTimeFormatter .ofLocalizedTime(FormatStyle.SHORT) .withLocale(Locale.GERMAN); LocalTime leetTime = LocalTime.parse("13:37", germanFormatter); System.out.println(leetTime); // 13:37
LocalDate displays a specific date, for example 2014-03-11. Instances are immutable and work similarly to LocalTime. The example demonstrates how to calculate a new date by adding or subtracting days, months or years. Keep in mind that every operation on an object returns a new object. LocalDate today =; LocalDate tomorrow =, ChronoUnit.DAYS); LocalDate yesterday = tomorrow.minusDays(2); LocalDate independenceDay = LocalDate.of(2014, Month.JULY, 4); DayOfWeek dayOfWeek = independenceDay.getDayOfWeek(); System.out.println(dayOfWeek); // FRIDAY Parsing LocalDate from a string is as simple as parsing LocalTime: DateTimeFormatter germanFormatter = DateTimeFormatter .ofLocalizedDate(FormatStyle.MEDIUM) .withLocale(Locale.GERMAN); LocalDate xmas = LocalDate.parse("24.12.2014", germanFormatter); System.out.println(xmas); // 2014-12-24
LocalDateTime displays the datetime. This is a combination of the date and time given above, in one copy. LocalDateTime instances are immutable and work similarly to LocalTime and LocalDate. We can use methods to retrieve the instance property values ​​we need: LocalDateTime sylvester = LocalDateTime.of(2014, Month.DECEMBER, 31, 23, 59, 59); DayOfWeek dayOfWeek = sylvester.getDayOfWeek(); System.out.println(dayOfWeek); // WEDNESDAY Month month = sylvester.getMonth(); System.out.println(month); // DECEMBER long minuteOfDay = sylvester.getLong(ChronoField.MINUTE_OF_DAY); System.out.println(minuteOfDay); // 1439 Together with additional time zone information, the instance can be converted to instant. Instants can be easily converted to the old types inheriting from java.util.Date. Instant instant = sylvester .atZone(ZoneId.systemDefault()) .toInstant(); Date legacyDate = Date.from(instant); System.out.println(legacyDate); // Wed Dec 31 23:59:59 CET 2014 Formatting a date-time works the same way as formatting a date or time. Instead of using predefined date formats, we can use manually defined formats. DateTimeFormatter formatter = DateTimeFormatter .ofPattern("MMM dd, yyyy - HH:mm"); LocalDateTime parsed = LocalDateTime.parse("Nov 03, 2014 - 07:13", formatter); String string = formatter.format(parsed); System.out.println(string); // Nov 03, 2014 - 07:13 Unlike java.text.NumberFormat, the new DateTimeFormatter is immutable and thread safe. For more information about the syntax for writing formats, read here .


Annotations in Java 8 are repeatable. Let's look at an example to illustrate how this works. To begin, we'll define an annotation wrapper that stores an array of valid annotations: @interface Hints { Hint[] value(); } @Repeatable(Hints.class) @interface Hint { String value(); } Java 8 enables us to use multiple annotations of the same type by declaring the annotation @Repeatable. Option 1: Using the container annotation (old school) (Java 8 allows us to use multiple annotation of the same type by declaring a @Repeatable annotation .) Option 1: Using the annotation container (old school) @Hints({@Hint("hint1"), @Hint("hint2")}) class Person {} Option 2: Using repeatable annotations (new feature) @Hint("hint1") @Hint("hint2") class Person {} Using option two, the java compiler implicitly sets the @Hint annotation. This is important for reading annotation information through reflection. Hint hint = Person.class.getAnnotation(Hint.class); System.out.println(hint); // null Hints hints1 = Person.class.getAnnotation(Hints.class); System.out.println(hints1.value().length); // 2 Hint[] hints2 = Person.class.getAnnotationsByType(Hint.class); System.out.println(hints2.length); // 2 Although we haven't declared the @Hints annotation for the Person class , it can be read using the getAnnotation(Hints.class) method . However, a more convenient method is getAnnotationsByType , which provides access to all annotations using the @Hint annotation . In addition, the use of annotations in Java 8 expands to two purposes: @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) @interface MyAnnotation {}

This is all

My Java 8 Programming Tutorial is complete. If you want to learn more about all the new classes and API features in JDK 8, just read my next article. This will help you understand all the new classes and hidden features in JDK 8, such as Arrays.parallelSort , StampedLock , and CompletableFuture .