Lesson 13 - Date and Time in Kotlin- Parsing and comparing
In the previous lesson, Date and Time in Kotlin - Modifying and intervals, we learned to convert between
modify the inner value, and introduced time intervals. In today's Kotlin course
tutorial, we're going to finish with the topic of date and time. We'll get inner
values, parse using custom formats, and compare.
Retrieving the value
We read the value using properties, there's nothing which should surprise us:
val halloween = LocalDate.of(2016, Month.OCTOBER, 31) println("Year: " + halloween.year + ", month: " + halloween.monthValue + ", day: " + halloween.dayOfMonth)
Notice that when IntelliJ displays autocomplete or when we press Ctrl + Space, the original Java methods the Kotlin's properties originated from are shown on the left (in parentheses).
Year: 2016, month: 10, day: 31
Notice the use of the
getMonthValue() to retrieve the month
number. In this case, we had to use it because
return the value of the enumerated
If you ever encounter the older
beware that months were zero-based back then (January was
1 like it is now in
Parsing date and time
As you may already know, date and time often comes as a String, e.g. from the
user through the console, a file or the database. We then create a
LocalDateTime from the string value using the
method right on the data type as we're used to in Kotlin.
parse() method expects dates to be in the
yyyy-mm-dd format, date and times in the
yyyy-mm-ddThh:mm:ss format and times in the
format. All of the numbers have to have leading zeros if they're less than 10.
T isn't a typo. It's more of a separator for date and time:
val dateTime = LocalDateTime.parse("2016-12-08T10:20:30") val date = LocalDate.parse("2016-12-08") val time = LocalTime.parse("10:20:30") println(dateTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM))) println(date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM))) println(time.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM)))
Console application Dec 8, 2016 10:20:30 AM Dec 8, 2016 10:20:30 AM
Even more so, we'll need to parse an American date and time or date and time
in some other format. The default
T separator for date and time
isn't very user-friendly
val dateTime = LocalDateTime.parse("12/08/2016 10:20:30", DateTimeFormatter.ofPattern("M/d/y HH:mm:ss")) val date = LocalDate.parse("12/8/2016", DateTimeFormatter.ofPattern("M/d/y")) val time = LocalTime.parse("10:20:30", DateTimeFormatter.ofPattern("H:m:ss")) println(dateTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM))) println(date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM))) println(time.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM)))
Dec 8, 2016 10:20:30 AM Dec 8, 2016 10:20:30 AM
The easiest way to compare dates is using the operators
>=. Kotlin overloads
these operators using
compareTo(). We'll talk about the
compareTo() method in depth further in the course.
If it seems confusing to you, you can use the built-in methods from Java,
which it contains because unlike Kotlin, it doesn't support operator
overloading. These methods start with
is*(), let's go through
isAfter(date)- Returns whether the instance is after the date/date and time passed through the parameter (whether the value is greater).
isBefore(date)- Returns whether the instance is before the date/date and time passed through the parameter (whether the value is lesser).
isEqual(date)- Returns whether the instance is set to the same date and/or time as the instance passed through the parameter (whether the value is equal).
Easy enough, right? While on the topic of
is*() methods, let's
go over the rest of them:
isLeapYear- Returns whether the instance is set to a leap year or not.
isSupported(ChronoUnit)- Returns whether the instance supports a given chrono unit (e.g.
ChronoUnit.HOURSsince it doesn't carry any time information).
isLeapYear() is a method,
but Kotlin generated a property for us again.
Here’s an example of their use:
val halloween = LocalDate.of(2016, 10, 31) val christmas = LocalDate.of(2016, 12, 25) println("after: " + halloween.isAfter(christmas)); println("before: " + halloween.isBefore(christmas)) println("equals: " + christmas.isEqual(halloween)) println("equals: " + halloween.isEqual(halloween)) println("leap: " + halloween.isLeapYear) println("leap: " + halloween.withYear(2017).isLeapYear) println("supports hours: " + halloween.isSupported(ChronoUnit.HOURS)) println("supports years: " + halloween.isSupported(ChronoUnit.YEARS))
after: false before: true equals: false equals: true leap: true leap: false supports hours: false supports years: true
LocalTime, you may also encounter several other classes which you
may find useful rather for applications which main purpose is date and time
manipulation. Don’t worry, you'll get by with
most applications. However, you should be aware of the existence of the
Instant represents a date and time that is not related to the
calendar or to daylight saving. It's stored as a number of nanoseconds since
1/1/1970, which gives it a certain point on the UTC (universal
time) timeline. The following code will always print the same date and time no
matter where you're located on the planet:
val instantNow = Instant.now() println(instantNow)
Instant is only aware of universal time, so it'll differ from a
particular area's local time.
OffsetDateTime and ZonedDateTime
Now you know that
Instant is used for universal time and
LocalDateTime is used for a particular area’s local time. We
wouldn't be able to get a point on a timeline from
since it doesn't carry any area information.
Wouldn't it be great if there was a class where date and time would be local
and also carry the area information (timezone)? This way, we'd be able to
convert between various time zones in a unified way. Well, that's exactly what
ZonedDateTime class is there for.
In Kotlin, you may also encounter the
which is an intermediate structure carrying the timezone offset. However, it
comes without full timezone support.
In Kotlin, time zones are represented by the
Here's an example of its use (creating an instance based on a time zone):
val localDateTime = ZonedDateTime.now(ZoneId.of("America/New_York)) println(localDateTime)
You may now be thinking, that's a lot of classes. I suggest that you treat it rather as information to which you may return to when you need it. There are more classes in Kotlin than in many other programming languages. The best way to become a solid Kotlin programmer is to be patient and develop some endurance to the fact. On the other hand, this is why we're better paid than others We'll get to some more practical programming in the next lesson so as to take a break from the theoretical aspects of it all.
To top it all off, we’ll get acquainted with some more
ofEpochSecond()- A static method allowing us to create a
LocalDateTimeinstance from a Linux timestamp which was used to store dates in the past. In returns the number of seconds since
1/1/1970(the beginning of the Linux epoch), which is a huge number, and we also have to specify the nanoseconds (mostly 0) as well as the timezome (most often
ZoneOffset.UTC). The method is also available on
ofEpochDay()where it receives the number of days rather than seconds.
toEpochDay()- These methods do the exact opposite of the ones mentioned above. They convert the instance to the number of seconds/days since 1970.
That is all for date and time in Kotlin. We'll code a practical application in the next lesson, Diary with a database in Kotlin. It'll be an electronic diary.