1

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;
}
Dale Julian
  • 1,560
  • 18
  • 35
  • `Thu Jun 02 17:10:30 EDT 2016` vs `GMT` – Scary Wombat Jun 03 '16 at 00:34
  • @Scary Wombat it is 8 hours – Dale Julian Jun 03 '16 at 00:39
  • You're comparing EDT vs GMT. ALso you're offsetting te value even more when you change the timezone too.. – JoxTraex Jun 03 '16 at 00:41
  • You have a date/time in EDT a date/time in PHT that both correspond to the same timestamp. What is the problem exactly? – shmosel Jun 03 '16 at 00:43
  • Any idea on how I can get the Date in EDT in millis? – Dale Julian Jun 03 '16 at 00:43
  • Everyone has to learn this at some point. Not sure why downvotes. – Csteele5 Jun 03 '16 at 00:43
  • @shmosel the output I get from `date.toString()` is `June 2, 2016` while the output I get from `date.getTime()` is `June 3, 2016`. – Dale Julian Jun 03 '16 at 00:45
  • @DaleJulian `Date.getTime()` returns a millisecond timestamp, not a date. – shmosel Jun 03 '16 at 00:46
  • @shmosel so how can I set the `Calendar` to my Date(June 2, 2016)? – Dale Julian Jun 03 '16 at 00:49
  • @DaleJulian looks like you're doing it just fine. Still not seeing the problem. – shmosel Jun 03 '16 at 00:50
  • 1
    The value from gettime is a fixed point in time independent of timezones. It's both "Thursday, June 2nd 2016, 17:10:30 (GMT -4)" (or EDT) and "Friday, June 3rd 2016, 05:10:30 (GMT +8)" since that's the same instant in time. It is what it is because your parse method uses the system's timezone (EDT) to translate. If you were to parse the same string in a different place, you'd get a different value for getTime() because "05:10:30 pm" are different instants across the planet. – zapl Jun 03 '16 at 00:51
  • @shmosel let's put it this way. I want to get the millis of `June 2, 2016 05:10:30 pm` instead of the next day. – Dale Julian Jun 03 '16 at 00:55
  • @DaleJulian in what time zone? – shmosel Jun 03 '16 at 00:56
  • @DaleJulian you'll need to [set the timezone](http://stackoverflow.com/a/2891412/1553851) before parsing the date. – shmosel Jun 03 '16 at 01:01
  • @shmosel I did this and still returns an exact day after calendar.setTimeZone(TimeZone.getTimeZone("GMT+8")); – Dale Julian Jun 03 '16 at 01:19
  • 1
    @DaleJulian not on the calendar, on the parser (`SimpleDateFormat`). – shmosel Jun 03 '16 at 01:25
  • @shmosel Thank you very much! It is working now! But will this have an impact if the user is in another `TimeZone`? – Dale Julian Jun 03 '16 at 01:43
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/113691/discussion-between-shmosel-and-dale-julian). – shmosel Jun 03 '16 at 01:46
  • @shmosel Sorry, the problem was the Genymotion's TimeZone all along! – Dale Julian Jun 03 '16 at 01:48

2 Answers2

2

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

Dale Julian
  • 1,560
  • 18
  • 35
1

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 );
Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154