How to check if time in miliseconds is of today's time and it is under 10 seconds from the current time? - kotlin

I am getting the timestamp from the server response in a string like..
KS100V1C1-2C3AE8176DC1\1 {"timestamp":"3:7:2021 16:01:38","ChannelId_1":100}
KS100V1C1-2C3AE8176DC1\1 {"timestamp":"3:7:2021 16:01:48","ChannelId_1":100}
KS100V1C1-2C3AE8176DC1\1 {"timestamp":"3:7:2021 16:01:58","ChannelId_1":100}
I am getting this in 10 seconds of gap like shown is response 38sec,48sec,58sec...
I want to check if the timestamp is of today's and is the time under the 10 sec of current time. Like if the timestamp is "3:7:2021 16:01:38" and current time is "3:7:2021 16:01:48" it should return me true.
I have converted the String to Date and then to Long like this :
fun convertTimeToLong(time: String) : Long {
val formatter: DateFormat = SimpleDateFormat("dd:mm:yyyy hh:mm:ss")
val date = formatter.parse(time) as Date
Log.d("LongTime : ", date.time.toString())
return date.time
}
and to check if the time is under 10 seconds I tried this :
private val TEN_SECONDS = 10 * 60 * 10000
fun isTimeUnder10Seconds(timeStamp: Long): Boolean {
val tenAgo: Long = System.currentTimeMillis() - TEN_SECONDS
if (timeStamp < tenAgo) {
Log.d("10Seconds ?"," is older than 10 seconds")
return true
} else {
Log.d("10Seconds ?"," is not older than 10 seconds")
return false
}
}
But this is not seemed to be working as expected.
Please help.
Thank you..

I would do that by means of java.time:
Here's an example that compares your example values (and does not involve the current moment in time, that one's at the bottom):
import java.time.LocalDateTime
import java.time.ZonedDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
fun main() {
val isValid = isOfTodayAndNotOlderThanTenSeconds("6:7:2021 16:01:38", "6:7:2021 16:01:48")
println(isValid)
}
fun isOfTodayAndNotOlderThanTenSeconds(time: String, otherTime: String) : Boolean {
// provide a formatter that parses the timestamp format
val dtf = DateTimeFormatter.ofPattern("d:M:uuuu HH:mm:ss")
// provide a time zone
val zone = ZoneId.of("UTC")
// parse the two arguments and apply the same zone to each
val other = LocalDateTime.parse(otherTime, dtf).atZone(zone)
val thatTime = LocalDateTime.parse(time, dtf).atZone(zone)
// finally return if the days/dates are equal
return thatTime.toLocalDate().equals(other.toLocalDate())
// and the first argument is at most 10 seconds older
&& !thatTime.isBefore(other.minusSeconds(10))
}
This actually returns/prints true.
If you want to compare it with the moment now, adjust this fun to take only one argument and change the object to compare to:
fun isOfTodayAndNotOlderThanTenSeconds(time: String) : Boolean {
// provide a formatter that parses the timestamp format
val dtf = DateTimeFormatter.ofPattern("d:M:uuuu HH:mm:ss")
// provide a time zone
val zone = ZoneId.of("UTC")
// take the current moment in time in the defined zone
val other = ZonedDateTime.now(zone)
// parse the argument and apply the same zone
val thatTime = LocalDateTime.parse(time, dtf).atZone(zone)
// finally return if the days/dates are equal
return thatTime.toLocalDate().equals(other.toLocalDate())
// and the argument is at most 10 seconds older
&& !thatTime.isBefore(other.minusSeconds(10))
}

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

What is the best way in kotlin to convert an Int value to a Double in a certain format

I have the following numbers:
val first: Int = 531241180
val second: Int = 653345
What would be the best way to write a function which could get first and second as input and return the following values:
output of the fist to a Double value 53.1241180
output of the second to a Double value 6.53345
If you are allowed to specify, how many numbers you want to see before dot, you can write something like this, avoiding math operations
fun intToDouble(value: Int, integerPlaces: Int): Double {
val raw = value.toString()
val sb = StringBuilder(raw)
if(integerPlaces < sb.length()) {
sb.insert(integerPlaces, ".")
} else {
return 0.0 // return 0 if operation is illegal
}
return sb.toString().toDouble()
}

Find closest time range from current date

I have some list of objects. Each of them contains specific "from" and "to" time range specified.
So for example:
import org.joda.time.DateTime
data class MyObject(
val from: String?,
val to: String?
)
The asUtcDateTime() is just my extension method that converts the given String do DateTime
How can I find the nearest object which:
is not in today time range
will be closest from today (future or past)?
What I've tried so far is just to get the nearest MyObject from the past and future like so:
val now = DateTime.now()
val nearestPastSchedule = allSchedules
.sortedBy { it.to.asUtcDateTime() }
.filter { it.to.asUtcDateTime() != null }
.lastOrNull { it.to.asUtcDateTime()!!.millis < now.withTimeAtStartOfDay().millis }
val nearestFutureSchedule = allSchedules
.sortedBy { it.from.asUtcDateTime() }
.filter { it.from.asUtcDateTime() != null }
.lastOrNull { it.from.asUtcDateTime()!!.millis > now.withTimeAtStartOfDay().millis }
Don't know what would be good solution in terms of comparing them (considered that there are nullable) and also have the actual MyObject returned for each of them
Instead of sorting, you can find the specified element yourself. I do so by finding the absolute minimum difference between now and the time specified in the object.
For simplicity reasons, I adjusted the data class to use ZonedDateTime (assuming Java >=8 to be available):
data class MyObject(
val from: ZonedDateTime?,
val to: ZonedDateTime?
)
With that, you can filter and find the minimum absolute value between now and the corresponding time:
val nearestPastSchedule =
allSchedules.filter { it.to != null }
.minBy { abs(it.to!!.toInstant().toEpochMilli() - now) }
val nearestFutureSchedule =
allSchedules.filter { it.from != null }
.minBy { abs(it.from!!.toInstant().toEpochMilli() - now) }

Kotlin: How to iterate all dates within a Joda Interval?

I'd like to iterate all dates within a given Joda interval:
val interval = Interval(DateTime.now().minusDays(42), DateTime.now())
How to do that in Kotlin?
Heavily inspired by your current solution:
fun Interval.toDateTimes() = generateSequence(start) { it.plusDays(1) }
.takeWhile(::contains)
Usage:
interval.toDateTimes()
.forEach { println(it) }
If you need the LocalDate you could still do the following instead:
interval.toDateTimes()
.map(DateTime::toLocalDate)
.forEach { println(it) }
or as an extension function to Interval again:
fun Interval.toLocalDates() = toDateTimes().map(DateTime::toLocalDate)
If you want the end date to be inclusive instead, use takeWhile { it <= end } instead.
The following extension function gives a Sequence of LocalDate objects from the given Interval, which can be used to iterate those dates.
fun Interval.toLocalDates(): Sequence<LocalDate> = generateSequence(start) { d ->
d.plusDays(1).takeIf { it < end }
}.map(DateTime::toLocalDate)
Usage:
val interval = Interval(DateTime.now().minusDays(42), DateTime.now())
interval.toLocalDates().forEach {
println(it)
}
In this solution, the last day, DateTime.now() is not included in the Sequence since that's how Interval is implemented as well:
"A time interval represents a period of time between two instants. Intervals are inclusive of the start instant and exclusive of the end."
If, for any reason, you want to make it include the last day, just change the takeIf condition to it <= end.
I guess if you need it more than once, it would be better to overload rangeTo operator to allow this syntax
for (i in LocalDate.now() .. LocalDate.now().plusWeeks(1)) {
System.out.print(i) // 2018-08-30 2018-08-31 2018-09-01
}
Here is the code for operator extension:
operator fun LocalDate.rangeTo(other: LocalDate): LocalDateRange {
return LocalDateRange(this, other)
}
And necessary classes:
class LocalDateRange(override val start: LocalDate, override val endInclusive: LocalDate)
: ClosedRange<LocalDate>, Iterable<LocalDate> {
override fun iterator(): Iterator<LocalDate> {
return DateIterator(start, endInclusive)
}
}
class DateIterator(start: LocalDate, private val endInclusive: LocalDate)
: Iterator<LocalDate> {
private var current = start
override fun hasNext(): Boolean {
return current <= endInclusive
}
override fun next(): LocalDate {
current = current.plusDays(1)
return current
}
}
LocalDate is preferred nowadays, so we can simply iterate with day as number:
for (day in minDate.toEpochDay()..maxDate.toEpochDay()) {
// ...
}
or:
(minDate.toEpochDay()..maxDate.toEpochDay()).forEach {
// ...
}
Iterate with day as date:
generateSequence(minDate) { it.plusDays(1) }.takeWhile { it < maxDate }.forEach {
// it ...
}
or:
var day = minDate;
while (day < maxDate) {
day = day.plusDays(1);
// ...
}

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.