val calendar = Calendar.getInstance() and val date = Date() return incorrect time

Viewed 462

I write two functions to get the start time and end time. The end time is always the current time and the start time is always the current time minus 2 seconds.

Here is the function code.

private fun getStartDateTime(): String {
    val dateFormat = SimpleDateFormat(Constants.SERVER_DATE_FORMAT, Locale.getDefault())
    val calendar = Calendar.getInstance() 
    calendar.add(Calendar.SECOND, -2)
    return dateFormat.format(calendar.time)
}

private fun getEndDateTime(): String {
    val dateFormat = SimpleDateFormat(Constants.SERVER_DATE_FORMAT, Locale.getDefault())
    val date = Date()
    return dateFormat.format(date)
}

In most of the devices, it's working as aspected but when I test this in Oneplus 6 it starts giving me the same time when I call this function. Please see the below screenshot of the local database table. enter image description here

Question: Those functions are called on every 2 seconds. So the start time and end time should be unique. Is there any reason why I'm not getting a unique start time and end time?

Edit

Those functions are called while creating a new object of the call like

val abc = ABC(xxx, xxx, xxx, getStartDateTime(), getEndDateTime())
2 Answers

Your approach is flawed.

Since your start date-time and end date-time are interdependent, you should derive one from the other. The problem with your approach is that you are deriving both, start date-time and end date-time from their times of the computation i.e. you are having two variable quantities (the computation time of start date-time and that of the end date-time) instead of one.

Given below is the Java code to do it and I hope, you will be able to convert it into Kotlin:

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

public class Main {
    public static void main(String[] args) throws ParseException {
        // Test
        System.out.println(getStartDateTime());
        System.out.println(getEndDateTime());
    }

    /**
     * 
     * Derives start date-time from end date-time
     * 
     * @throws ParseException
     */
    private static String getStartDateTime() throws ParseException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
        Date date = dateFormat.parse(getEndDateTime());// Get end date-time
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.SECOND, -2);
        return dateFormat.format(calendar.getTime());
    }

    private static String getEndDateTime() {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
        Date date = new Date();
        return dateFormat.format(date);
    }
}

Output from a sample run:

2020-09-28 11:26:58
2020-09-28 11:27:00

A piece of advice:

I recommend you switch from the outdated and error-prone java.util date-time API and SimpleDateFormat to the modern java.time date-time API and the corresponding formatting API (package, java.time.format). Learn more about the modern date-time API from Trail: Date Time. If your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Using the modern date-time API:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(getStartDateTime());
        System.out.println(getEndDateTime());
    }

    /**
     * 
     * Derives start date-time from end date-time
     * 
     */
    private static String getStartDateTime() {
        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.getDefault());
        LocalDateTime ldt = LocalDateTime.parse(getEndDateTime(), dateFormat);// Get end date-time
        return dateFormat.format(ldt.minusSeconds(2));
    }

    private static String getEndDateTime() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.getDefault()));
    }
}

It’s guesswork. Some possible explanations include:

  • (Unlikely.) The clock on your device has stopped.
  • (Unlikely.) The implementations of Calendar.getInstance() and Date() on that device cache too much and give you a value from a stale cache.
  • The scheduler doesn’t work on that device and calls your function much more often than every 2 seconds. As a likely variant, multiple schedulers are running, each calling every 2 seconds.
  • By some error your object gets inserted into your database many times with different IDs.

We don’t have any information that will allow us to come closer. As chrylis -cautiouslyoptimistic- said in a comment, you may do some logging from your function to see how many times it is really getting called within the time your program is running. Aslo how does 1332 entries compare to the expected number?

As an aside, if you can, prefer to use java.time, the modern Java date and time API, as explained in the last half of the other answer. If the problem is indeed a stale cache, this is also very likely to avoid that problem.

Related