Dale Julian
Dale Julian

Reputation: 1588

Android Date.getTime() adds one day to original Date

So I have a calendar that I need to set a specific date to..

    Date date = TKDateUtils.parseDate("Jun 02, 2016 05:10:30 pm");

    Calendar next = Calendar.getInstance();
    next.setTime(date);

and I log them here to see the output:

    Log.i("MainActivity", date.toString());
    Log.i("MainActivity", date.getTime() + "");

Output:

    06-02 20:21:29.245 1915-1915/com.cyscorpions.timekeeper I/MainActivity: Thu Jun 02 17:10:30 EDT 2016
    06-02 20:21:29.245 1915-1915/com.cyscorpions.timekeeper I/MainActivity: 1464901830000

So I convert the getTime from millis to Date and this is the output:

enter image description here

So the Date is set to June 2, 2016 17:10:30 but the getTime() is set to the exact day after that date. Am I doing something wrong here?

Here is how I parse the date:

public static Date parseDate(@NonNull String dateString) {
    try {
        mDateFormat = new SimpleDateFormat("MMM dd, yyyy h:mm:ss a");
        return mDateFormat.parse(dateString);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return null;
}

Upvotes: 1

Views: 2877

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 338835

Specify Time Zone

Two different JVMs, each with its own (different) current default time zone. Each used its own current default time zone during parsing of the string to interpret the meaning of the input data.

Solution: Always specify the desired/expected time zone.

The JVM’s current default time zone can be initialized in various ways. And the current default time zone can be changed during runtime by any code in any thread of any app within the JVM. So never depend on this externality of time zone.

Specify a proper time zone name, in format of continent/region. Never use the 3-4 letter abbreviations such as EDT, IST, CST, etc. These are not true time zones, are not standardized, and are not unique(!).

Specify Locale

Same goes for Locale, used in parsing name of day & month, determining comma vs period, and such. The JVM’s current default Locale is out of your control. So always specify the desired/expected Locale appropriate to the context of your input data.

java.time

You are using old date-time classes that have proven to be poorly designed, confusing, and troublesome. Avoid them.

The java.time classes are built into Java 8 and later. Much of their functionality has been back-ported to Java 6 & 7 in the ThreeTen-Backport project, and further adapted to Android in the ThreeTenABP project.

The java.time classes are the successor to the highly successful Joda-Time library, both projects led by the same man, Stephen Colbourne. The java.time classes supplant the notoriously troublesome old date-time classes bundled with the earliest versions of Java.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MMM dd, yyyy h:mm:ss a" );
formatter = formatter.withLocale( locale );
formatter = formatter.withZone( zoneId );

ZonedDateTime zdt = ZonedDateTime.parse( input , formatter );

We often want to work with values in UTC. For this, use Instant, a moment on the timeline in UTC with a resolution of nanosecond.

Instant instant = zdt.toInstant();

Convert

If you must have one of the old types, use new methods added to the old date-time classes to convert to/from java.time.

java.util.Date utilDate = java.util.Date.from( instant );
java.util.Calendar utilCal = java.util.GregorianCalendar.from( zdt );

Upvotes: 1

Dale Julian
Dale Julian

Reputation: 1588

The problem was on Genymotion's TimeZone all along. It is set to a different timezone from my location.

Upvotes: 2

Related Questions