Question

I need to parse a custom defined date format, defined in a device that I need to communicate where the date is given as the number of seconds counted from the year 2000.

I tried to use GregorianCalendar to parse this data, this is the code I tried:

    GregorianCalendar calendar = new GregorianCalendar();
    calendar.setGregorianChange(new Date(2000 - 1900, 0, 1));

The Date object corresponds to January 1st 2000. And I thought that with this I was fine to setTimeInMillis to get the correct date multiplying the time I read by 1000, as it's counted in seconds not in miliseconds as GregorianCalendar, but it didn't work. I tried setTimeInMillis(0), waiting that the time corresponding to calendar corresponds to January 1st 2000 but it doesn't, it corresponds to December 18th 1969.

How can I configure GregorianCalendar so I can setTimeInMillis(0) and it corresponds to January 1st 2000? If it's not possible, is there any other class I can use instead of creating all the code by myself?

Thanks in advance.

Was it helpful?

Solution

setGregorianChange only changes the point in time where the switch from Julian to Gregorian happened. It defaults to the correct historical value.

But since pretty much everyone else out there is using proleptic Gregorian, there is a valid use case for this function:

setGregorianChange(new Date(Long.MIN_VALUE)) //Julian never happened

This is also what JodaTime uses by default.

Anyway, you can just subtract 946684800000L from the normal millisecond unix timestamp, and divide by 1000:

public static long secondsSince2000(Date input) {
    final long epoch = 946684800000L;
    return (input.getTime() - epoch) / 1000L;
}

To convert from seconds since 2000:

public static Calendar fromSecondsSince2000( long seconds ) {
    final long epoch = 946684800000L;
    Calendar cal = GregorianCalendar.getInstance();
    long timestamp = epoch + seconds * 1000L;
    cal.setTime(new Date(timestamp));
    return cal;
}

To see that both are working:

    long sec = secondsSince2000(new Date());
    Calendar cal = fromSecondsSince2000( sec );
    System.out.println(cal.getTime().toString().equals(new Date().toString()));

They should print true

OTHER TIPS

Create a Date to 2000/01/01 and get the time in milliseconds, then get the time in milliseconds from your device. Add the two and create Dates and Calendars to your hearts desire...

You are using deprecated constructor for Date. Moreover, you are using it wrong way.

It should be GregorianCalendar(year + 1900, month, date). according to Oracle Docs

BTW why not use JodaTime? Then you get many handy stuff:

DateTime dt = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour);

What you want to do is to change the Epoch, which is 2000/01/01 by default (Unix timestamp). So what you want to have is simply a kind of Unix timestamp with 2000/01/01 as Epoch.

I would get the unix timestamp in millis of 2000/01/01 and save it as a constant. Now, subclass GregorianCalendar so that you can add these millis from your input data and return the correct dates.

Maybe you can also take a look at JSR-310

This would do

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")); // change the timezone as you wish
cal.set(Calendar.YEAR, 2000);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DATE, 1);   
cal.set(Calendar.HOUR, 00);
cal.set(Calendar.MINUTE, 00);
cal.set(Calendar.SECOND, 00);
cal.set(Calendar.MILLISECOND, 00);

cal.add(Calendar.MILLISECOND, 1000); // calculate and add your millisec here where 1000 is added 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top