How to know pattern of string date in kotlin - kotlin

I want to convert in ZonedDateTime. How can I recognise pattern to pass in DateTimeFormatter.ofPattern(????????).
val string = "May 9, 2020 8:09:03 PM"
private fun getFormatDate(date: String): ZonedDateTime {
val dateTimeFormatter = DateTimeFormatter.ofPattern(????????)
return ZonedDateTime.parse(date, dateTimeFormatter)
}
Many Thanks

You can do:
private fun getFormatDate(date: String): ZonedDateTime {
val dateTimeFormatter =
DateTimeFormatter
.ofPattern("MMM d, yyyy h:mm:ss a")
.withZone(ZoneId.systemDefault()) // or some other zone that you would like to use
.withLocale(Locale.ENGLISH)
return ZonedDateTime.parse(date, dateTimeFormatter)
}
Note that it is important that you do .withZone which specifies the zone that the ZonedDateTime is going to have, and also .withLocale, so that the parser interprets things like "May" and "PM" in the correct language.
Try It Online
See all the pattern letters here

Related

How to compare LocalDateTime instances in kotlin

so I'm having a little problem with kotlin LocalDateTime
val now = CurrentDateTime
val someDate = someService.someLocalDateTime
I have two dates as you can see and I want to know if now is bigger than someDate or not.
and also I need to know if it's bigger, how much is bigger.
i can do it by checking year, month, day, minute and second like this:
if (now.year().toString() == someDate.year.toString())
but it's not a good way
any suggesstions would be welcome.
You can simply convert both dates in seconds and:
compare them to know which one is bigger
subtract them to know how much one is bigger than the other
an example would be
val now = CurrentDateTime.toEpochSeconds()
val someDate = someService.someLocalDateTime.toEpochSeconds();
if(now > someDate)
//someDate is in the past
else
//someDate is in the future or both dates are equal
val distance = now-someDate
hope this helps
The standard solution to compare two Date objects is by using the compareTo() function. It returns a value
= 0, if both dates are equal.
< 0, if date is before the specified date.
> 0, if date is after the specified date.
The following program demonstrates it:
import java.text.SimpleDateFormat
import java.util.*
fun main() {
val now = CurrentDateTime // "01/21/2023"
val someDate = someService.someLocalDateTime // "01/21/2020"
val sdf = SimpleDateFormat("MM/dd/yyyy")
val firstDate: Date = sdf.parse(now)
val secondDate: Date = sdf.parse(someDate)
val cmp = firstDate.compareTo(secondDate)
when {
cmp > 0 -> {
System.out.printf("%s is after %s", d1, d2)
}
cmp < 0 -> {
System.out.printf("%s is before %s", d1, d2)
}
else -> {
print("Both dates are equal")
}
}
}
Convert Kotlin LocalDateTime to Java LocalDateTime
To convert Kotlin LocalDateTime to Java LocalDateTime, you can make use of this function:
fun LocalDateTime.toJavaLocalDateTime(): LocalDateTime
Converts this kotlinx.datetime.LocalDateTime value to a java.time.LocalDateTime value.
And then you can choose to use the following method or other suggested method to compare the converted java.time.LocalDateTime.
Compare Java LocalDateTime
To compare LocalDateTime, you can use LocalDateTime's isAfter(), isBefore(), isEqual().
import java.time.LocalDateTime
fun main() {
val currentTime = LocalDateTime.now()
val ytdTime = LocalDateTime.now().minusDays(1)
println(currentTime.isAfter(ytdTime))
println(currentTime.isBefore(ytdTime))
println(currentTime.isEqual(ytdTime))
}
Output
true
false
false
To find the difference between LocalDateTime, you can use ChronoUnit:
import java.time.temporal.ChronoUnit
fun main() {
val currentTime = LocalDateTime.now()
val ytdTime = LocalDateTime.now().minusDays(1)
val secondDifference = ChronoUnit.SECONDS.between(ytdTime, currentTime)
val minutesDifference = ChronoUnit.MINUTES.between(ytdTime, currentTime)
val hourDifference = ChronoUnit.HOURS.between(ytdTime, currentTime)
println(secondDifference)
println(minutesDifference)
println(hourDifference)
}
Output
86399
1439
23

Date format using kotlin

I would like to reformat a string from
14 Sep 2021 to 14 Sep using the SimpleDateFormat or any other APIs.
Currently my code looks like this:
private fun convertToDayAndMonth(date: String): String{
val dateFormat: Date = SimpleDateFormat("dd MMM yyyy").parse(date)!!
return SimpleDateFormat("d MMM").format(dateFormat)
but i am getting an error that says "14 Sep 2021" cannot be parsed
must be just syntax errors in your code.
both of these work for me:
println(myConvertToDayAndMonth("14 Sep 2021"))
fun myConvertToDayAndMonth(dateString: String): String {
val sdf: SimpleDateFormat = SimpleDateFormat("dd MMM yyyy")
val date: Date = sdf.parse(dateString)
return SimpleDateFormat("d MMM").format(date)
}
println(convertToDayAndMonth("14 Sep 2021"))
fun convertToDayAndMonth(date: String): String {
val javaDate: Date = SimpleDateFormat("dd MMM yyyy").parse(date)!!
return SimpleDateFormat("d MMM").format(javaDate)
}

Kotlin - how to parse a string that is either in a LocalDateTime or LocalDate format into LocalDate

I have a mapper where I am getting a string that is either in this format:
"2021-06-08" or "2021-06-08T15:00"
in my mapper I should convert this string always into a LocalDate:
ExcelColumn.CHANGED_DATE -> rowData
.nullLocalDate(column.dbColumnName)
?.format(excelV2DateFormat)
nullLocalDate looks like this:
fun Entity.nullLocalDate(key: String): LocalDate? = if (this[key] == null) null else localDate(key)
fun Entity.localDate(key: String): LocalDate = when (val v = this[key]) {
is LocalDateTime -> v.toLocalDate()
is Instant -> LocalDate.ofInstant(v, ZoneId.of("UTC"))
is String -> LocalDate.parse(v)
else -> v as LocalDate
}
I also have a function that checks nullLocalDateTime:
fun Entity.nullLocalDateTime(key: String): LocalDateTime? = if (this[key] == null) null else localDateTime(key)
fun Entity.localDateTime(key: String, zoneId: ZoneId? = null): LocalDateTime = when (val v = this[key]) {
is Instant -> LocalDateTime.ofInstant(v, zoneId ?: ZoneId.of("UTC"))
is String -> LocalDateTime.parse(v)
else -> v as LocalDateTime
}
I can use one or the other, but how can I combine this two to check if it is either in localDate or localDateTime format and convert it into localDate in both cases?
As of now it works fine if the value is in format "2021-06-08", but it fails if the string is in the format of "2021-06-08T15:00":
java.time.format.DateTimeParseException: Text '2021-06-08T15:00' could not be parsed, unparsed text found at index 10
How can I accommodate both cases in one function?
You can define optional parts in the pattern of a DateTimeFormatter. In your case, you'd want:
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm]")
Where the ['T'HH:mm] defines the optional time part. You can then use this formatter when parsing your strings into LocalDate instances. There are a few ways this can be done, but the easiest and most readable is to use the LocalDate#parse(CharSequence,DateTimeFormatter) method.
Runnable example:
import java.time.LocalDate
import java.time.format.DateTimeFormatter
fun main() {
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm]")
val dateOnlyString = "2021-06-08"
val dateAndTimeString = "2021-06-08T15:00"
val parsedDateOnly = LocalDate.parse(dateOnlyString, formatter)
val parsedDateAndTime = LocalDate.parse(dateAndTimeString, formatter)
println("parse(\"$dateOnlyString\") --> $parsedDateOnly")
println("parse(\"$dateAndTimeString\") --> $parsedDateAndTime")
}
Output:
parse("2021-06-08") --> 2021-06-08
parse("2021-06-08T15:00") --> 2021-06-08

Working with Date and LocalDate

I want to use an array of data class where one of the parameters is Date, I could not use Date() as it looks to be related to KotlinJS, so I tried using LocalDate so I wrote the below code:
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.*
data class transaction (var date: LocalDate, var quantity: Double)
val formatter: DateTimeFormatter
get() = DateTimeFormatter.ofPattern("dd.mm.yyyy", Locale.ENGLISH)
fun main(args: Array<String>) {
var salesOrders = ArrayList<transaction>()
println("Hello, world! ")
salesOrders.set(0, transaction(LocalDate.parse("01.02.2018", formatter), 0.0))
println(salesOrders)
}
But, as shown at tryKotlin I'm getting an error, that:
Text '01.02.2018' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {Year=2018, MinuteOfHour=2, DayOfMonth=1}.
As described in the DateTimeFormatter documentation, the "m" character in the pattern means "minute"; "month" is "M". You need to change "mm" to "MM".
it must be MM not mm see DateTimeFormatter

Kotlin convert TimeStamp to DateTime

I'm trying to find out how I can convert timestamp to datetime in Kotlin, this is very simple in Java but I cant find any equivalent of it in Kotlin.
For example: epoch timestamp (seconds since 1970-01-01) 1510500494 ==> DateTime object 2017-11-12 18:28:14.
Is there any solution for this in Kotlin or do I have to use Java syntax in Kotlin? Please give me a simple sample to show how I can resolve this problem.
this link is not an answer to my question
private fun getDateTime(s: String): String? {
try {
val sdf = SimpleDateFormat("MM/dd/yyyy")
val netDate = Date(Long.parseLong(s) * 1000)
return sdf.format(netDate)
} catch (e: Exception) {
return e.toString()
}
}
It's actually just like Java. Try this:
val stamp = Timestamp(System.currentTimeMillis())
val date = Date(stamp.time)
println(date)
class DateTest {
private val simpleDateFormat = SimpleDateFormat("dd MMMM yyyy, HH:mm:ss", Locale.ENGLISH)
#Test
fun testDate() {
val time = 1560507488
println(getDateString(time)) // 14 June 2019, 13:18:08
}
private fun getDateString(time: Long) : String = simpleDateFormat.format(time * 1000L)
private fun getDateString(time: Int) : String = simpleDateFormat.format(time * 1000L)
}
Notice that we multiply by 1000L, not 1000. In case you have an integer number (1560507488) muliplied by 1000, you will get a wrong result: 17 January 1970, 17:25:59.
Although it's Kotlin, you still have to use the Java API. An example for Java 8+ APIs converting the value 1510500494 which you mentioned in the question comments:
import java.time.*
val dt = Instant.ofEpochSecond(1510500494)
.atZone(ZoneId.systemDefault())
.toLocalDateTime()
Here is a solution in Kotlin
fun getShortDate(ts:Long?):String{
if(ts == null) return ""
//Get instance of calendar
val calendar = Calendar.getInstance(Locale.getDefault())
//get current date from ts
calendar.timeInMillis = ts
//return formatted date
return android.text.format.DateFormat.format("E, dd MMM yyyy", calendar).toString()
}
val sdf = SimpleDateFormat("dd/MM/yy hh:mm a")
val netDate = Date(item.timestamp)
val date =sdf.format(netDate)
Log.e("Tag","Formatted Date"+date)
"sdf" is variable "SimpleDateFormat" of where we can set format of date as we want.
"netDate" is variable of Date. In Date we can sending timestamp values and printing that Date by SimpleDateFormat by using sdf.format(netDate).
This worked for me - takes a Long
import java.time.*
private fun getDateTimeFromEpocLongOfSeconds(epoc: Long): String? {
try {
val netDate = Date(epoc*1000)
return netDate.toString()
} catch (e: Exception) {
return e.toString()
}
}
#SuppressLint("SimpleDateFormat")
fun dateFormatter(milliseconds: String): String {
return SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(Date(milliseconds.toLong())).toString()
}
This is a improved version existing answers (Sahil's and Javier's)
val stamp = Timestamp(System.currentTimeMillis()) // from java.sql.timestamp
val date = Date(stamp.time)
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
// set your timezone appropriately or use `TimeZone.getDefault()`
sdf.timeZone = TimeZone.getTimeZone("Asia/Kolkata")
val formattedDate = sdf.format(date)
println(formattedDate)
Kotlin Playground link
Improvements
Set time zone to get correct time otherwise you will get the UTC time.
Formatted the date time according to yyyy-MM-dd HH:mm:ss format.
Disambiguate the Timestamp class import by commenting the required import.
Added Kotlin Playground link to see a working example.
fun stringtoDate(dates: String): Date {
val sdf = SimpleDateFormat("EEE, MMM dd yyyy",
Locale.ENGLISH)
var date: Date? = null
try {
date = sdf.parse(dates)
println(date)
} catch (e: ParseException) {
e.printStackTrace()
}
return date!!
}
If you're trying to convert timestamp from firebase.
This is what worked for me.
val timestamp = data[TIMESTAMP] as com.google.firebase.Timestamp
val date = timestamp.toDate()
This works for me.
fun FromTimestamp(value: Long?): Date? {
return if (value == null) null else Date(value)
}
private fun epochToIso8601(time: Long): String {
val format = "dd MMM yyyy HH:mm:ss" // you can add the format you need
val sdf = SimpleDateFormat(format, Locale.getDefault()) // default local
sdf.timeZone = TimeZone.getDefault() // set anytime zone you need
return sdf.format(Date(time * 1000))
}
The above code will get the time in long format, which is the default epoch format and return it as a string to display.
In case you have input as a string just add .toLong() and it will be converted to long.