kotlinx-datetime icon indicating copy to clipboard operation
kotlinx-datetime copied to clipboard

DateTimeFormatter equivalent

Open ArcherEmiya05 opened this issue 2 years ago • 5 comments

It is not included in the documentation so we would like to ask if Kotlinx Datetime has java.time.format.DateTimeFormatter equivalent for formatting?

Here are the following usage we had with the Java DateTimeFormatter

val formattedDate: String
        get() = LocalDate.parse(date, DateTimeFormatter.ISO_LOCAL_DATE_TIME).format(
            DateTimeFormatter.ofPattern("MMM. dd, yyyy")
        )
  val formattedTime: String = Instant.ofEpochMilli(time).atZone(ZoneId.systemDefault())
  .toLocalDate().format(DateTimeFormatter.ofPattern("MM-dd-yyyy"))
LocalDateTime.parse(
                  lowDate,
                  DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")
              )

Currently using coreLibraryDesugaringEnabled for backward compatibility.

ArcherEmiya05 avatar May 26 '22 07:05 ArcherEmiya05

Have you seen the issues labeled with 'formatter'?

JakeWharton avatar May 26 '22 12:05 JakeWharton

Have you seen the issues labeled with 'formatter'?

You mean this?

Flexible locale-neutral parsing and formatting facilities are needed to support various date/time interchange formats that are used in practice (in particular, various RFCs).

Sorry but does that mean it is not yet supported?

ArcherEmiya05 avatar May 26 '22 18:05 ArcherEmiya05

Sorry but does that mean it is not yet supported?

Yes.

Regarding the LocalDateTime.parse usage though, it closely resembles ISO-8601, so you can do that:

Instant.parse(lowDate).toLocalDateTime(TimeZone.UTC)

dkhalanskyjb avatar May 30 '22 10:05 dkhalanskyjb

Sorry but does that mean it is not yet supported?

Yes.

Regarding the LocalDateTime.parse usage though, it closely resembles ISO-8601, so you can do that:

Instant.parse(lowDate).toLocalDateTime(TimeZone.UTC)

Thanks a lot, is there any alternative formatter we can use specially when working with KMM?

ArcherEmiya05 avatar May 30 '22 11:05 ArcherEmiya05

@ArcherEmiya05 Because it is on the timeline, I ended up just writing a simple common shim for formatting/parsing which delegates to klock under the hood, since that library has a working multiplatform implementation. I'll be switching over as soon as this one also does. For pet projects at least, maybe this will also work for you.

jlnstrk avatar Jun 09 '22 12:06 jlnstrk

My usecase was very limited (and only needing to support Android & iOS) so I ended up just going for this very simple util, posting here incase it helps someone.

In commonMain:

import kotlinx.datetime.LocalDateTime

expect fun LocalDateTime.format(format: String): String

androidMain:

import java.time.format.DateTimeFormatter

import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.toJavaLocalDateTime

actual fun LocalDateTime.format(
    format: String
): String = DateTimeFormatter.ofPattern(format).format(this.toJavaLocalDateTime())

iosMain:

import platform.Foundation.NSCalendar
import platform.Foundation.NSDateFormatter

import kotlinx.datetime.LocalDateTime

actual fun LocalDateTime.format(format: String): String {
    val dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = format
    return dateFormatter.stringFromDate(
        toNSDate(NSCalendar.currentCalendar)
            ?: throw IllegalStateException("Could not convert kotlin date to NSDate $this")
    )
}

SamCosta1 avatar Oct 20 '22 15:10 SamCosta1

On the basis of @SamCosta1 , I changed it again, and corrected the possible parameter errors.

in common Main

expect fun Instant.formatDate(pattern: String, defValue: String = ""): String

expect fun String.parseDate(pattern: String, defValue: Long = 0L): Long

fun Long.formatDate(pattern: String, defValue: String = ""): String {
  return Instant.fromEpochMilliseconds(this).formatDate(pattern, defValue)
}

in iosMain

actual fun Instant.formatDate(pattern: String, defValue: String): String {
  return try {
    val dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = pattern
    dateFormatter.stringFromDate(
      toNSDate()
    )
  } catch (e: Exception) {
    defValue
  }

}

actual fun String.parseDate(pattern: String, defValue: Long): Long {
  return try {
    val dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = pattern
    val result = dateFormatter.dateFromString(this)?.timeIntervalSince1970?.toLong()
    if (result != null) {
      result * 1000
    } else {
      defValue
    }
  } catch (e: Exception) {
    defValue
  }
}

in JVM and Android:

actual fun Instant.formatDate(pattern: String, defValue: String): String {
  return try {
    SimpleDateFormat(pattern).format(Date(this.toEpochMilliseconds()))
  } catch (e: Exception) {
    defValue
  }
}

actual fun String.parseDate(pattern: String, defValue: Long): Long {
  return try {
    SimpleDateFormat(pattern).parse(this).time
  } catch (e: Exception) {
    defValue
  }
}

CherryLover avatar Dec 28 '23 03:12 CherryLover