-3

I have written this code to compare two time values in milliseconds. The comparison is of current time with the time defined in the database.

fun check_for_lecture(complete:(Boolean) -> Unit) : Int{

     for (x in UpdateScheduledLecturesService.lectures) {
         try {
             val start_time = x.start_time.toInt()
             val end_time = x.end_time.toInt()
             val timeRightnow = System.currentTimeMillis().toInt()

         // CompareTo returns a negative number if it's less than other, or a positive number if it's greater than other.
         //(also tried)if (timeRightnow == start_time || timeRightnow > start_time  && timeRightnow < end_time) {

             val compareWstarttime= timeRightnow.compareTo(start_time)
             val compareWendtime = timeRightnow.compareTo(end_time)
             if(compareWstarttime > 0 && compareWendtime < 0){
             count++
             lectureID = x.lectureID
             Log.d(TAG, "Test: lectureId assigned")
             complete(true)
             } else {
                 Log.d(TAG, "no lectures at this time")
                 complete(false)
             }
         } catch (e: ParseException) {
             Log.d(TAG, "Exception")
             e.printStackTrace()
             complete(false)
         }
     }

However, it is not working. I am not sure where I am going wrong.

This is an example of when I print them:

current time :436239119, start time : 1520845200, end time : 1520848800.

tsttt2
  • 90
  • 4
avi silwal
  • 31
  • 1
  • 7
  • Tracking time as a count-from-epoch is clumsy, error-prone, and difficult to troubleshoot. Instead use the *java.time* classes. See [the Answer](https://stackoverflow.com/a/49236674/642706) by Ole V.V. for a more practical approach. – Basil Bourque Mar 12 '18 at 20:02

3 Answers3

3

System.currentTimeMillis() returns a long value, and when converting to int, you're losing its precision.

Example: I've ran a code right now, and System.currentTimeMillis() returned 1520856967725. That's more than 1.5 trillion, which is too big to fit in an int (the max value for an int is 2147483647 - around 2.1 billion).

When you convert to an int, it gets only the last 32 bits and that big value becomes 438544942:

10110001000011010001000111010101000101101 - 1520856967725
         00011010001000111010101000101101 - 438544942 (last 32 bits)

To make your code work, convert your start and end times to long, because that's the correct type to fit the values you're comparing. And don't convert currentTimeMillis to int, because, well, it's a long value.

PS: Another detail is that currentTimeMillis returns the number of milliseconds since unix epoch. But some API's also work with the number of seconds. Make sure what values are returned by your start and end times before comparing as well (based on your values, it seems that start and end times are in seconds - if that's the case, you should divide currentTimeMillis by 1000 before converting it to anything).

tsttt2
  • 90
  • 4
1

Your problem is that your start time and your end time are in seconds since the epoch, while System.currentTimeMillis() (as the name says) gives you milliseconds since the epoch. So the values cannot readily be compared.

The banal solution is to multiply the first two or divide the third by 1000 before comparing. However, such arithmetic operations on date-time values are not very friendly towards the next programmer trying to read and understand the code.

Instead I recommend you use a library class both for conversion and for comparison. Instant from java.time, the modern Java date and time API, is the one you need. I am sorry I cannot write Kotlin code, but I trust that translating from Java won’t be too hard:

    long start_time = x.getStart_time();
    long end_time = x.getEnd_time();
    Instant timeRightnow = Instant.now();
    if (timeRightnow.isAfter(Instant.ofEpochSecond(start_time)) 
            && timeRightnow.isBefore(Instant.ofEpochSecond(end_time))) {
        // do something
    }

Better yet if you can use a datetime datatype in your database instead of storing seconds since the epoch. That would make output from queries to the database much more readable and generally help debugging. And eliminate your problem.

Question: Can I use java.time on Android?

Yes, you can use java.time on Android. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices the modern API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

you can use joda apis.Example below

import org.joda.time.DateTime;

public class CompareDateTimes {

  public static void main(String[] args) {

    // dt1 and dt2 have the same date and time
    DateTime dt1 = new DateTime();
    DateTime dt2 = new DateTime(dt1);

    // dt3 is one day later
    DateTime dt3 = new DateTime(dt2.plusDays(1));

    System.out.println("dt1.equals(dt2): " + dt1.equals(dt2));
    System.out.println("dt1.equals(dt3): " + dt1.equals(dt3));

    System.out.println("dt1.isAfter(dt3): " + dt1.isAfter(dt3));
    System.out.println("dt1.isBefore(dt3): " + dt1.isBefore(dt3));
  }
}
spandey
  • 1,034
  • 1
  • 15
  • 30
  • I am not able to pass the miliseconds to DateTime parameter, it is throwing this error : "1520845200" is malformed at "0" . – avi silwal Mar 12 '18 at 12:21
  • FYI… The *Joda-Time* project is now in maintenance mode with its authors recommending migration to the *java.time* classes. For earlier Android, see the *ThreeTen-Backport* and *ThreeTenABP* projects. – Basil Bourque Mar 12 '18 at 16:51