Date Formatting With Kotlin Multiplatform | by Gorm Sorensen | Jun, 2022

Write a easy multiplatform date formatter utilizing 1) native libraries or 2) kotlinx.datetime

Clock and calendar
Picture by Towfiqu barbhuiya on Unsplash

Formatting dates usually feels borderline tiresome to implement. Personally, each time I’ve to transform a date to a sure format, I believe to myself — now once more? Didn’t we do that earlier than? There needs to be a approach of penning this type of code as soon as and never having to trouble with it once more.

A easy instance of a date formatting requirement may very well be that we should show the textual content 18.06.2022 if (you guessed it) the present date is June 18th, 2022. Must be simple sufficient to do on a number of platforms, proper? Certain. However it’s a must to write the “similar” formatting logic twice for those who write code for Android and iOS, for instance, in two separate code bases.

Fortunately for us, we are able to make the most of Kotlin Multiplatform Mobile (KMM) which allows us to write down the identical code as soon as and use it throughout a number of platforms.

I gained’t go into element about KMM on this publish. Let’s go straight to the purpose and dive into the code as a substitute.

On this publish I’ll current two alternate options:

  1. A generic formatter written purely in Kotlin, the place we’ll add code to commonMain , androidMain , and iosMain , thereby introducing platform-specific logic;
  2. Utilizing a multiplatform library referred to as kotlinx-datetime (verify the repo here), the place we’ll preserve all of our code in commonMain .

For brevity, I’ll solely concentrate on supporting timestamps in ISO 8601 format, in addition to solely supporting one date format, particularly dd.MM.yyyy .

Let’s outline this straightforward class which we put in commonMain:

(Sure, DateTime isn’t an ideal identify for such a category. We may identify it Iso8601TimestampFormatter or equally, however I selected to call it otherwise for brevity.)

It’s fairly fundamental. We cross in an ISO 8601 timestamp in addition to a format (dd.MM.yyyy), and it ought to return the formatted date.

So how does it look on Android?

We are going to make the most of the java.time APIs, though it requires our Android minimal SDK to be 26 (you should use ThreeTen Backport or desugaring if you wish to use these APIs on decrease SDK variations).

The next needs to be positioned in androidMain :

We’re parsing our timestamp utilizing the ZonedDateTime API, and subsequently formatting it with our format through DateTimeFormatter .

Then how about iOS?

As a substitute of utilizing Java libraries, which aren’t accessible on iOS, we’ll as a substitute confer with the Basis framework. It incorporates all of the issues we’d like for date formatting (and more, in fact).

Let’s put the next in iosMain :

We create an occasion of NSDateFormatter and set the time zone, locale, and format. Lastly, we invoke stringFromDate() to get the formatted string.

You could ask — why not use the Swift APIs like DateFormatter , TimeZone , and so forth.? The TL;DR is that we’re unable to import any pure Swift modules from Kotlin code within the present state of KMM. Importing Goal-C APIs (NS…), nonetheless, works simply high-quality. See this link for more information.

Let’s check it! ✅

As our assessments are platform-independent, it’s adequate to put them in commonTest solely:

After we ask Android Studio to run the assessments, we’re requested to make use of a particular goal (relying on how our venture is configured):

Screenshot of Android Studio when running all tests in DateTimeTests
Screenshot of Android Studio when operating all assessments in DateTimeTests

Usually you’d select between :testDebugUnitTest and iosX64 . Operating both, we are able to see that the assessments cross:

Test results (all passed)
Check outcomes

If you happen to don’t need to run the assessments through Android Studio’s popup (or having to waste treasured time deciding on completely different choices in a popup, for that matter), you possibly can merely run the command $ ./gradlew :shared:allTests which is able to execute all assessments within the venture throughout all potential targets.

Alright, cool, however I don’t actually need to write platform-dependent code if it may be prevented

Let’s see if we are able to keep away from that, then! The great individuals over at Kotlin/JetBrains created the kotlinx-datetime library, which we’ll take a look at subsequent.

I like to recommend studying the documentation on the GitHub page for this library. As for our work, let’s get proper right down to it by including the dependency to our commonMain supply set:

Now let’s use Immediate and LocalDateTime to search out the day, month, and 12 months from the timestamp, and eventually return the formatted date as a string:

The zeroPrefixed() extension operate is one I created to bypass the truth that there’s no non-JVM String.format() equal in Kotlin’s customary library at this moment, which might in any other case allow us to simply format integers as strings with prefixed zeros. You’ll find the code for zeroPrefixed() here.

Write the assessments (why wouldn’t you?)

We checked out two approaches to writing date formatting logic that works on each Android and iOS.

Requiring platform-specific logic, the primary method allows us to make use of date time patterns/codecs straight. Nonetheless, we’re pressured to write down code that caters to every particular person platform.

Evidently, the method needing much less code is the latter. It depends on a third-party library that doesn’t at this moment help formatting varied date time patterns/codecs out of the field, which is why now we have to write down that half ourselves. On the intense facet, it’s a multiplatform library, and we don’t have to fret about any platform-specific APIs.

Hope you will have enjoyable coding in Kotlin for a number of platforms!

More Posts