2

I've been trying to convert the time since epoch until today and display it in Eastern Standard Time. Here is what outputs on the remote machine (it's remotely hosted):

Date now = new Date(System.currentTimeMillis());
System.out.println(now.toString());
// Thu Apr 24 14:36:11 MST 2014

No idea what MST is, but I want to get the current milliseconds since epoch in EST, and display the result in EST.

No matter what I do, I can't get daylights savings to work (it's currently Daylights Savings Time in the EST Time Zone); I either end up in PST, GMT or UTC, and when I do get "EST" it's either some random value or 1 hour behind or 3 hours behind.

I would like the output to be formatted using this DateFormat:

DateFormat EXPIRE_FORMAT = new SimpleDateFormat("MMM dd, yyyy h:mm a z");
Nahydrin
  • 13,197
  • 12
  • 59
  • 101
  • Where are you geographically right now? Also, `SimpleDateFormat` has a `setTimeZone` method. – Sotirios Delimanolis Apr 24 '14 at 21:42
  • I'm in Ontario, Canada. (EST) – Nahydrin Apr 24 '14 at 21:42
  • MST seems to be Mountain Standard Time but doesn't seem to cover Ontario. – Sotirios Delimanolis Apr 24 '14 at 21:43
  • The server I'm running this on is somewhere in the United States, the input time needs to work regardless of where it's located. – Nahydrin Apr 24 '14 at 21:44
  • 1
    I am from Melbourne, Australia which has Eastern Standard Time (EST) The three letter codes are not unique. – Peter Lawrey Apr 24 '14 at 21:51
  • 1
    Technically, right now EST does not apply, but rather EDT (Eastern Daylight Time). You probably just mean "Eastern Time" (either standard or daylight depending on which is applicable). You simply need to apply a time zone. You can use either `"America/New_York"`, or if you prefer, `"America/Toronto"` or `"America/Montreal"`. – Matt Johnson-Pint Apr 24 '14 at 21:53
  • BTW The Cayman Islands use US/EST all year and don't have daylight saving. ;) – Peter Lawrey Apr 24 '14 at 21:57
  • 2
    @PeterLawrey - Which is why there exists a distinct zone for `"America/Cayman"`. [The TZDB](http://www.iana.org/time-zones) is pretty good at knowing these things. :) See also [here](http://en.wikipedia.org/wiki/Tz_database) and [here](http://en.wikipedia.org/wiki/List_of_tz_database_time_zones). – Matt Johnson-Pint Apr 24 '14 at 22:05
  • 2
    @PeterLawrey - Also, thanks for mentioning the issue with abbreviations. [Time zone abbreviations](http://en.wikipedia.org/wiki/Time_zone_abbreviations) are highly ambiguous and overlapping - yet some folks seem to think they are unique keys. :) – Matt Johnson-Pint Apr 24 '14 at 22:07
  • @MattJohnson I used to think EST was unique for a long time. In general you only hear about the ones used locally and *everyone* knows what you mean when you are in a particular country. However, computers are more pedantic. – Peter Lawrey Apr 24 '14 at 22:09

2 Answers2

3

Just set the time zone you want the time to be displayed in using DateFormat#setTimeZone(TimeZone)

Date now = new Date(System.currentTimeMillis());
DateFormat EXPIRE_FORMAT = new SimpleDateFormat("MMM dd, yyyy h:mm a z");
EXPIRE_FORMAT.setTimeZone(TimeZone.getTimeZone("America/Montreal")); // or whatever relevant TimeZone id 
System.out.println(EXPIRE_FORMAT.format(now));

AFAIK, there is no EST currently. It's all EDT in Spring.

The above prints

Apr 24, 2014 5:53 PM EDT
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • 2
    Please avoid backward compatibility zones like `"US/Eastern"`. Examples should prefer canonical zones like `"America/New_York"`. Thanks. – Matt Johnson-Pint Apr 24 '14 at 21:54
  • @MattJohnson I'm from Montreal :). Can you explain why those are problematic? – Sotirios Delimanolis Apr 24 '14 at 21:56
  • 1
    Ahh, [here's](http://stackoverflow.com/questions/9523917/are-us-eastern-and-us-central-and-us-pacific-deprecated-for-strftime-or-ju) an explanation. – Sotirios Delimanolis Apr 24 '14 at 21:59
  • 3
    Yes, the reasons in that link are valid. Particularly, the TZDB moves backward compatibility links to the ["backward" file](https://github.com/eggert/tz/blob/master/backward). The `US/*` zones were originally created to align with POSIX standards. Also, there are minor variations between New York, Montreal, and Toronto in their past history. Lumping them all into "Eastern" isn't very accurate. – Matt Johnson-Pint Apr 24 '14 at 22:02
2

The comments and the answer by Sotirios Delimanolis are correct.

Avoid 3 or 4 Letter Time Zone Codes

You should avoid the 3 or 4 letter codes for time zones as they are neither standardized nor unique. Instead use proper time zone names, usually a continent+city.

Avoid j.u.Date

The java.util.Date and .Calendar & SimpleDateFormat classes bundled with Java are notoriously troublesome. Use a decent date-time library with an updated time zone database. For Java, that means either Joda-Time or the new java.time package in Java 8 (inspired by Joda-Time).

Avoid Milliseconds-Since-Epoch

I suggest you avoid working with milliseconds since epoch. Gets confusing fast as the number is meaningless when read by a human. Let the date-time library manage the milliseconds for you.

Specify Time Zone

Generally best to specify the desired/intended time zone. If you omit the time zone, all the major date-time libraries (java.util.Date, Joda-Time, java.time) apply the JVM's default time zone.

Joda-Time Example

Example code in Joda-Time 2.3.

DateTimeZone timeZoneToronto = DateTimeZone.forID( "America/Toronto" );
DateTime dateTimeToronto = new DateTime( timeZoneToronto ); // Current moment.
DateTime dateTimeUTC = dateTimeToronto.withZone( DateTimeZone.UTC );
DateTime dateTimeParis = dateTimeToronto.withZone( DateTimeZone.forID( "Europe/Paris" ) );

If you really want the milliseconds since epoch, call the getMillis method. In example code above, all three DateTime objects have the same number of milliseconds-since-epoch.

long millis = dateTimeToronto.getMillis();

If you need a java.util.Date for use with other classes…

java.util.Date date = dateTimeToronto.toDate();

While Joda-Time uses the ISO 8601 standard formats as its defaults, you may specify other formats for generating strings.

DateTimeFormatter formatter = DateTimeFormat.forPattern( "MMM dd, yyyy h:mm a z" );
String output = formatter.print( dateTimeToronto );
Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154