Miguel Betegón
Miguel Betegón

Reputation: 53

What is the best way to operate with time in kotlin?

I am developing an Android app using Kotlin and I would like to achieve the following:

  1. Let a user select a time for an alert (hh:mm) from current time until the following 24 hours e.g. at 16:00 user wants to put an alert for tomorrow at 15:00.
  2. Once the user has set the alert, I want to show the time remaining until the alert is activated (hh:mm) e.g. Show a small dialog with the text: 3h:15min remaining.

What is the best way to deal with time operations (subtract current time to the alert time) in Kotlin?

Upvotes: 1

Views: 1997

Answers (2)

Miguel Betegón
Miguel Betegón

Reputation: 53

According to Basil Bourque, the following is the code he proposed (in Java) converted to Kotlin, just in case someone is interested.


// Credit to Basil Bourque Answer
// https://stackoverflow.com/questions/59846004/what-is-the-best-way-to-operate-with-time-in-kotlin/59846550#59846550

lateinit var zdt: ZonedDateTime
val targetLocaltime = LocalTime.of(21, 0)
val z = ZoneId.of("Europe/Madrid")
val now = ZonedDateTime.now(z)
val runToday = now.toLocalTime().isBefore(targetLocaltime)

zdt = if (runToday){
    now.with(targetLocaltime)
}
else{
    now.toLocalDate().plusDays(1).atStartOfDay(z).with(targetLocaltime)
}
val eta = Duration.between(now.toInstant(), zdt.toInstant()).toMinutes()
if(eta > 60){
    val hours = eta / 60
    val minutes = eta % 60
    print("$hours:$minutes remaining")
}
else{
    print("$eta minutes remaining")
}

Upvotes: 0

Basil Bourque
Basil Bourque

Reputation: 338775

All your questions have been asked and answered many times on Stack Overflow. So I’ll be brief. Search to learn more.

Use only java.time classes, never the terrible legacy classes such as Date and Calendar.

For Android before 26, see the ThreeTen-Backport library and its Android-specific wrapper ThreeTenABP.

Represent a time-of-day with LocalTime.

LocalTime targetLocalTime = LocalTime.of( 15 , 0 ) ;

Get current moment. Requires a time zone. 2-4 letter codes like CST are not real time zones. Real zones are named Continent/Region.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;

Compare time portion. Extract a LocalTime to compare.

Boolean runToday = now.toLocalTime().isBefore( targetLocalTime ) ;

Determining next alarm time.

ZonedDateTime zdt = now.with( targetLocalTime ) ; 

Or if needed on next day, tomorrow.

ZonedDateTime zdt = now.toLocalDate().plusDays( 1 ).atStartOfDay( z ).with( targetLocalTime ) ;

Calculate elapsed time. Adjust to UTC by extracting an Instant.

Duration d = Duration.between( now.toInstant() , zdt.toInstant() ) ;

Generate string in standard ISO 8601 format.

String output = d.toString() ;

Or generate a string in another format by calling the Duration::to…Part methods.

As for firing the alarm, in straight Java use the Executors framework, specifically ScheduledExecutorService. This framework makes it simple to run a background thread that fires a task Runnable at a certain moment. Well, nearly certain — slight delays may occur for garbage-collection or thread/process scheduling on the CPU, but good enough for business apps (not good enough for NASA).

Android may also provide some alarm-setting feature. (I don’t know)

Never ever access or manipulate your user-interface from a background thread. Use whatever hook Android provides to update the UI from another thread, such as refreshing a UI widget or presenting a notification.

Upvotes: 4

Related Questions