Lesson 11 - Date and Time in Kotlin - Creating and formatting
In the previous lesson, Properties in Kotlin, we introduced you to getter and setter properties in Kotlin. Today, we're going to explore other classes which Kotlin provides through Java. You’ll learn how to work with date and time.
Date and time in Kotlin
Kotlin doesn't have its own date and time implementation. Why should the Kotlin developers focus on something Oracle created in Java 8? As we emphasized in the Kotlin basic course, Kotlin and Java are "compatible", they use the same virtual machine and that's why they can share their classes. Therefore, Kotlin uses Java classes for date and time.
Unfortunately, Java's implementation of date and time has changed multiple times in the past. Many of the early attempts weren't very successful, up to the point where third-party libraries were used instead. Although we're going to use the implementation introduced in Java 8, let’s go over the legacy (old) classes since you'll encounter them in other projects, sooner or later:
Date
- The Date class from thejava.util
package was the first attempt of storing date and time in Java. It's still there for the sake of backward compatibility, however, almost all of its methods are now marked as deprecated. We won't deal with this class at all. If you ever encounter it and want to know exactly how it works, use the official documentation - https://docs.oracle.com/…il/Date.htmlCalendar
- The Calendar class is the first replacement of the initialDate
class, which brought things like localization or better manipulation with the inner values. That way, you were able to add time interval and so on. Don't use it for new projects. However, since Java 8 is still relatively new, you'll see this class for sure.LocalDate
,LocalTime
, andLocalDateTime
- Since Java 8, theLocalDateTime
class and its variants are used exclusively for date and/or time. When we compare it to theCalendar
class, it's immutable. Which means, simply put, that we can use it when working with threads (more on this in later Kotlin courses). It also provides a fluent interface which is sometimes referred to as method chaining. Another good thing about it is that it doesn't mix getting and setting different value parts into a single method. Instead, it provides a variety of separated methods to do so. It surpasses the originalCalendar
class in both quality and in the number of features.- Joda-Time - The unsuccessful attempts of implementing date
and time in Java resulted in a need for a high-quality replacement for built-in
classes. The Joda-Time library became quite popular at this point in time. The
new Java 8 date API was inspired, in many ways, by this library and even uses
the same concepts. One might even say that Joda-Time might be more powerful and
of higher quality. However, I suggest that you keep using the standard
LocalDateTime
class and avoid unnecessary dependencies on third-party components.
Dealing with a large amount of classes is, whether you like it or not, part of a Java/Kotlin programmer’s daily routine. We'll dedicate three articles to date and time. With all of that being said, let's get right to it!
LocalDateTime, LocalDate and LocalTime
As we already know, we'll use the LocalDateTime
,
LocalDate
, and LocalTime
classes based on whether we
need to store both date and time (e.g. a flight departure), date only (e.g. a
birth date), or time only (e.g.: 10:00, nanosecond accuracy).
Creating instances
We'll start by creating instances of those classes. Create a new project and
name it DateAndTime
.
Creating an instance from given values
When we create a new instance of one of the classes, we call the
factory of()
method on the class and pass the
appropriate parameters to it. The method has multiple overloads. You can specify
seconds, or a month by a number or by an enumerated type (which is probably more
readable, more about them later on in the course) as well as several others.
// Date and time val dateTime = LocalDateTime.of(2016, Month.APRIL, 15, 3, 15) println(dateTime) // Date only val date = LocalDate.of(2016, Month.APRIL, 15) println(date) // Time only val time = LocalTime.of(3, 15, 10) println(time)
Don't forget to import the classes:
import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime import java.time.Month
The output:
2016-04-15T03:15 2016-04-15 03:15:10
Creating the current date and time instance
As you already know, we'll have to retrieve the current date and time in lots
of future applications. To do so, we’ll call the
now()
factory method right on the corresponding
class:
// Current date and time val dateTime = LocalDateTime.now() println(dateTime) // Curent date val date = LocalDate.now() println(date) // Current time val time = LocalTime.now() println(time)
Formatting
The output isn't user-friendly at all, so let's format it! As you may have
guessed, we're going to use the format()
method to
do so. However, this time, we'll call it on an instance. The formatting will
then be provided by the DateTimeFormatter
class. We'll be using the
following static methods on it:
- ofLocalizedDateTime() - Formats to a local date and time format. It takes two parameters - the date style and the time style. We can choose anything from the full format to the short format, this applies for all of the methods except for ofPattern().
- ofLocalizedDate() - Formats to the local date format
- ofLocalizedTime() - Formats to the local time format
- ofPattern() - Unlike the above methods which formatted using the user's regional settings, this method allow us to specify a custom format as a string containing format symbols. For example, the day, month, year, hours, minutes, and seconds (all numbers) would be passed as the following string "M/d/y H:m:ss". The description of all of the symbols is quite exhausting and can be found in the official Java documentation - https://docs.oracle.com/…rmatter.html
Here's an example of each method:
val dateTime = LocalDateTime.now()
println(dateTime.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM)))
println(dateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)))
println(dateTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT)))
println(dateTime.format(DateTimeFormatter.ofPattern("M/d/y H:m:ss")))
Don't forget to add imports:
import java.time.format.DateTimeFormatter import java.time.format.FormatStyle
The result:
8:13:04 PM Friday, December 9, 2016 December 9, 2016 8:13 PM 12/9/2016 20:13:04
The date and time will be localized depending on your operating system language.
Notice how we set the style (using the FormatStyle
enum), which
indicates whether we want a full or a brief output. We can use the following
values:
FULL
- Returns the date as "Friday, December 6, 2016". This one is not suitable for time and throws an exception if used this way.LONG
- Returns the date as "December 6, 2016". Isn't suitable for time and throws an exception if used this way.MEDIUM
- Returns the date as "Dec 6, 2016", the time as "3:15:10".SHORT
- Returns the date as "12/6/2016", the time as "3:15".
There are also some predefined ISO formats available as constants on the
DateTimeFormatter
class. However, they're not very user friendly,
so we won't use them.
Since date and time in Kotlin is a rather long topic, we'll continue
discussing it in the next lesson, Date and Time in Kotlin - Modifying and intervals, as well. We'll convert between
LocalDate
, LocalTime
, and LocalDateTime
as well as modify the inner value and introduce time intervals.