HydroHeiperGen
HydroHeiperGen

Reputation: 121

Why does Calendar.getTimeInMillis() returns negative value?

I am reading the date of a textview and i want to know the unix time at 00.00 am.

Working with API 23.

Following is my shot at achieving it:

String sDate = mainBinding.tvTakeTimeCurrentShownDateDateFormat.getText().toString();
      Calendar actuallDate = Calendar.getInstance();

    Log.d(TAG, "oc_bt_TakeTime_lastDate: " + sDate.substring(6,8)+ " " + Integer.parseInt(sDate.substring(6,8)));
    Log.d(TAG, "oc_bt_TakeTime_lastDate: "+ sDate.substring(3,5) + " " + Integer.parseInt(sDate.substring(3,5)));
    Log.d(TAG, "oc_bt_TakeTime_lastDate: " + sDate.substring(0,2) + " " + Integer.parseInt(sDate.substring(0,2)));

      actuallDate.clear();
      actuallDate.set(Integer.parseInt(sDate.substring(6,8)), (Integer.parseInt(sDate.substring(3,5))-1), Integer.parseInt(sDate.substring(0,2)), 0, 0 ,0);

    Log.d(TAG, "oc_bt_TakeTime_lastDate: " + actuallDate.get(Calendar.DAY_OF_MONTH)+actuallDate.get(Calendar.MONTH)+actuallDate.get(Calendar.YEAR));

    Log.d(TAG, "oc_bt_TakeTime_lastDate: " + String.valueOf(actuallDate.getTimeInMillis()));

I casted it to long because I thought it might produce an overflow by casting to an int.

result:

oc_bt_TakeTime_lastDate: 19 19
oc_bt_TakeTime_lastDate: 08 8
oc_bt_TakeTime_lastDate: 24 24
oc_bt_TakeTime_lastDate: 24719
oc_bt_TakeTime_lastDate: -61547472000000

Upvotes: 0

Views: 821

Answers (3)

Anonymous
Anonymous

Reputation: 86399

You are overcomplicating things.

java.time and ThreeTenABP

I could not read from your question exactly how your string looks. For this answer I am assuming 24.08.19. If you cannot adapt the answer to your real string, please revert in comments.

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd.MM.uu");
    String sDate = "24.08.19";
    LocalDate actualDate = LocalDate.parse(sDate, dateFormatter);
    System.out.println("Actual date: " + actualDate);
    long epochMilli = actualDate.atStartOfDay(ZoneId.systemDefault())
            .toInstant()
            .toEpochMilli();
    System.out.println("Milliseconds since the epoch: " + epochMilli);

Output on my computer in Europe/Copenhagen time zone is:

Actual date: 2019-08-24
Milliseconds since the epoch: 1566597600000

The Calendar class that you were trying to use is poorly designed and long outdated. You should not use it. For a date use LocalDate from java.time, the modern Java date and time API.

Don’t hand parse your string the way you were doing. The DateTimeFormatter class has been built in for this purpose, so leave the work to it. This also buys you a better validation of the string. uu or yy in a format pattern string will parse a 2-digit year like 19 into a year in the interval from 2000 through 2099.

What went wrong in your code?

jmart is correct: You were setting the year to year 19 common era. That’s 2000 years ago now. Since the epoch from which the milliseconds are counted was in 1970, you’re bound to get a negative number. As you have seen, using the formatter for parsing solves this problem for you.

Question: Can I use java.time on Android API level 23?

Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the modern 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

Upvotes: 1

jmart
jmart

Reputation: 2941

As you can see on the second-to-last display, you are setting the year 0019, not the year 2019. As getTimeInMillis is set in relation to the epoch time (Jan 1, 1970), you get a negative number.

Upvotes: 4

Yash
Yash

Reputation: 3576

I'll suggest this workaround:

  1. Create a Date object using current timestamp
  2. Use that object to set your calendar object

    Date d = new Date(timestampLong);
    Calendar actuallDate = Calendar.getInstance();
    actuallDate.setTime(d);

Upvotes: 0

Related Questions