2

Given:

private Calendar calendarInstance = Calendar.getInstance();

public long inMillis() {
    calendarInstance.set(year, month, day, hour, min);
    return calendarInstance.getTimeInMillis();
}

As i understand it, the result comes back with time since the epoch, in milliseconds

The current time as UTC milliseconds from the epoch.

Given that my test always sets the objects the same, why are results coming up different as time goes by?

detailedMoment = new MomentInTime(2012, 11, 1, 19, 9);
detailedMoment.inMillis() // gives different results as time passes by

UPDATE:

I continue to second guess myself due to enter image description here

For the same time period i get

1_351_796_940 // http://www.epochconverter.com
1_354_410_540 // my number
James Raitsev
  • 92,517
  • 154
  • 335
  • 470

4 Answers4

2

Well you don't set the seconds or milliseconds. JavaDoc says:

Sets the year, month, day of the month, hour of day and minute fields. Other fields are not changed.

Jacob Schoen
  • 14,034
  • 15
  • 82
  • 102
koljaTM
  • 10,064
  • 2
  • 40
  • 42
2

I think you should use clear(). If you do that it will return you the exact number of miliseconds each time.

public long inMillis() {
    calendarInstance.clear();
    calendarInstance.set(year, month, day, hour, min);
    return calendarInstance.getTimeInMillis();
}

From Java doc

Sets all the calendar field values and the time value (millisecond offset from the Epoch) of this Calendar undefined. This means that isSet() will return false for all the calendar fields, and the date and time calculations will treat the fields as if they had never been set. A Calendar implementation class may use its specific default field values for date/time calculations. For example, GregorianCalendar uses 1970 if the YEAR field value is undefined.

A Sample program

public class MomentInTime {

private static Calendar calendarInstance = Calendar.getInstance();

public static long inMillis() {
    calendarInstance.clear();
    calendarInstance.set(2012, 10, 1, 19, 9);
    return calendarInstance.getTimeInMillis();
}

public static void main(String[] args) throws InterruptedException {
    for (int i = 0; i < 10; i++) {
        System.out.println(inMillis()/1000);
        Thread.sleep(300);
    }
}
}

Output:

 1351777140

enter image description here

Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72
  • @Jam I checked it and I get consistent results with It.I even converted to Date and checked it returns appropriate value. – Amit Deshpande Nov 01 '12 at 20:11
  • My numbers seem to disagree with http://www.epochconverter.com. What do you get when getting time in milliseconds on date above – James Raitsev Nov 01 '12 at 20:13
  • @Jam Added a Sample you can check the out put it is same for that day though there is sleep and time is changing. – Amit Deshpande Nov 01 '12 at 20:17
  • Thank you. You're absolutely right. Can you please glance above and help explain possible number discrepancy. – James Raitsev Nov 01 '12 at 20:17
  • @Jam Problem might be because you are not specifying time zone and converting to GMT. Check with Local time zone. My values match exactly. You have to create calendar instance using Timezone GMT to match with GMT – Amit Deshpande Nov 01 '12 at 20:29
  • Thank you again Amit for your time, example and thorough explanation – James Raitsev Nov 01 '12 at 20:30
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18941/discussion-between-jam-and-amitd) – James Raitsev Nov 01 '12 at 21:02
1

I guess that is because you are missing seconds and milliseconds of the Calendar.getInstance().

You are just replacing year, month, day, hour, min of Calendar object, but every time when you get calendar instance, seconds and milliseconds of that particular point in time may change.

kosa
  • 65,990
  • 13
  • 130
  • 167
1

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Solution using java.time, the modern Date-Time API:

import java.time.LocalDate;
import java.time.ZoneOffset;

public class Main {
    public static void main(String[] args) {
        //Test
        System.out.println(inMillis(2021,6,19,8,30));
    }
    public static long inMillis(int year, int month, int day, int hour, int min) {
        return LocalDate.now()
                .atStartOfDay(ZoneOffset.UTC)
                .withYear(year)
                .withMonth(month)
                .withDayOfMonth(day)
                .withHour(hour)
                .withMinute(min)
                .toInstant()
                .toEpochMilli();
    }
}

Output:

1624091400000

ONLINE DEMO

This is how http://www.epochconverter.com displays it:

enter image description here

Learn more about the modern Date-Time API from Trail: Date Time.

Update:

A simpler version (thanks to Ole V.V.):

public static long inMillis(int year, int month, int day, int hour, int min) {
    return OffsetDateTime.of(year, month, day, hour, min, 0, 0, ZoneOffset.UTC)
            .toInstant()
            .toEpochMilli();
}

* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and 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.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • Thanks for showing the modern solution that is definitely recommended these days. Would `OffsetDateTime.of(2012, 11, 1, 19, 9, 0, 0, ZoneOffset.UTC).toInstant().toEpochMilli()` seem simpler? (yields 1 351 796 940 000, which seems to agree with the asker’s expectations.) – Ole V.V. Jun 19 '21 at 07:53