2

I have a date String with following format: MM/DD/2019 Possible values could be 1/16/2019 or 11/31/2019 for example.

I'm searching a way to convert this String values to get the following format:

2019-11-31 15:07:57.013Z

How can I do that in Kotlin ?

wawanopoulos
  • 9,614
  • 31
  • 111
  • 166
  • https://www.codevscolor.com/how-to-convert-a-string-to-date-in-kotlin/ – fantaghirocco Nov 15 '19 at 13:16
  • 5
    Why should `11/31/2019` be a possible value? – MC Emperor Nov 15 '19 at 13:16
  • 2
    How do you want to add the time part if you only get dates to be parsed? – deHaar Nov 15 '19 at 13:20
  • Regarding your title, the format you want is not ISO. *Separating date and time parts with other characters such as space is not allowed in ISO 8601,…* ([Wikipedia](https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations)) – Ole V.V. Nov 15 '19 at 19:02

3 Answers3

6

One of the great things of Kotlin is that you can reuse Java libraries, so java.time library can be used like this:

import org.junit.jupiter.api.Test
import java.time.LocalDate
import java.time.ZoneId
import java.time.format.DateTimeFormatter

class ApplicationTests {
    @Test
    fun changeDateFormat(){
        val inputDateString = "11/31/2019"
        val inputFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy")
        val localDate = LocalDate.parse(inputDateString, inputFormatter)
        val outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSZ")
        val localDateTime = localDate.atStartOfDay()
        val zonedDateTime = localDateTime.atZone(ZoneId.of("America/New_York"))
        val outputDateString = outputFormatter.format(zonedDateTime)
        print(outputDateString)
    }
}

Running that test will print 2019-12-01 00:00:00.000-0500 as output.

The new format has hours and minutes, so the LocalDate needs to be transformed into a LocalDateTime, and that can be done by atStartOfDay(), as an option there's atTime(H,M).

The new format also has a timezone, for that you need to transform it to ZonedDateTime the method .atZone(..) can be used for that.


java.text.SimpleDateFormat could also be used in a couple of lines:

val date = SimpleDateFormat("MM/dd/yyyy").parse("11/31/2019")
print(SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ").format(date))

But as @OleV.V. pointed out it's quite outdated and has some troubles (like not taking the time and timezone into account might be leading to undesired bugs).

rvazquezglez
  • 2,284
  • 28
  • 40
5

Please refer to this for ISO format conversion: https://mincong-h.github.io/2017/02/16/convert-date-to-string-in-java/

    String dateStr = "1/16/2019";

    Date date = new SimpleDateFormat("MM/dd/yyyy").parse(dateStr);

    SimpleDateFormat sdf;
    sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
    sdf.setTimeZone(TimeZone.getTimeZone("CET"));
    String dateText = sdf.format(date);

    System.out.println(dateText);
Surender Khairwa
  • 601
  • 4
  • 17
  • 3
    These date-time classes are terrible. They were supplanted years ago by the modern *java.time* classes defined in JSR 310. – Basil Bourque Nov 15 '19 at 14:26
  • 1
    It is a preferrable solution for Android, because `DateTimeFormatter` requires API 26, see https://stackoverflow.com/questions/50999112/date-and-time-in-android-studio-kotlin-language. – CoolMind May 06 '20 at 16:58
4

By using a DateTimeFormatter you can indicate in what format you provide the dates or expect the dates.

See it online: https://ideone.com/jDhi4x

import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.Locale

fun main(args: Array<String>) {
    val string = "1/16/2019"
    val formatter = DateTimeFormatter.ofPattern("M/d/yyyy", Locale.ENGLISH)
    val date = LocalDate.parse(string, formatter)
    println(date)
}
Tschallacka
  • 27,901
  • 14
  • 88
  • 133
  • 1
    Limited to SDK 26 and above only, for backward compatibility on older devices follow this https://developer.android.com/studio/write/java8-support#library-desugaring – Mihae Kheel Apr 09 '21 at 06:00