2

I have seen many resources on this but one thing I cant get is when converting the millisecond timestamp, how I add a corresponding time zone, during the conversion process.

Date date = new Date(Long.valueOf(dateInMil*1000L);
SimpleDateFormat myDate = new SimpleDateFormat("EEE, MMM d, ''yy");
String formatted = myDate.format(date);

Now if I have a time zone/offset in string formate i.e. "-04:00" or "+2:00" how to apply it to the above so I can get the proper date ?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Zee
  • 172
  • 1
  • 5
  • 12
  • Why are you converting milliseconds into microseconds? Is `dateInMil` actually seconds? – OneCricketeer Feb 09 '18 at 21:29
  • 1
    Note: If you are using Java 8, you should **not** be using `Date` or `Calendar` objects, and instead using `LocalDate`, for example – OneCricketeer Feb 09 '18 at 21:31
  • 1
    FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/9/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/9/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [java.time](https://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html) classes built into Java 8 & Java 9. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Feb 10 '18 at 02:40
  • 1
    Please search Stack Overflow before posting. These issues have been covered many times already. – Basil Bourque Feb 10 '18 at 02:55
  • You are really asking two questions in one and should instead post them as two questions: how to parse an offset like `"-04:00"` and how to convert milliseconds to date at a given offset. – Ole V.V. Feb 10 '18 at 07:27

4 Answers4

5

tl;dr

Instant.ofEpochMilli( myCountOfMilliseconds ) 
       .atZone( ZoneId.of( "Africa/Tunis" ) )
       .toString()

java.time

The modern approach uses the java.time classes rather than the troublesome old Calendar/Date classes that are now legacy.

Assuming your count of milliseconds is a count since the epoch reference of first moment of 1970 in UTC (1970-01-01T00:00), then parse as a Instant.

The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant instant = Instant.ofEpochMilli( myCountOfMilliseconds ) ;

To move from UTC to another time zone, apply a ZoneId to get a ZonedDateTime.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

Objects vs text

After assigning the time zone, then generate a string in your desired format (not before). You may be conflating date-time values (objects) with strings representing their value textually. Learn to think of smart objects, not dumb strings.

DateTimeFormatter

To generate a String in a particular format, use a DateTimeFormatter. Search Stack Overflow as this been covered many many times, as have the other concepts shown here. Of special note are the DateTimeFormatter.ofLocalized… methods.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
3

I was doing a similar thing in my previous project.You can use setTimeZone method of SimpleDateFormat class. Something like this :

mydate.setTimeZone(TimeZone.getTimeZone("GMT -0400"));
  • Theoretically, if you insist on using the outmoded classes, this should be the correct solution. However, no matter if I put `GMT -1400` or `GMT +1400`, I still get the same date. The old classes are more troublesome than one would think. I discourage using them. Use `java.time` instead. – Ole V.V. Feb 10 '18 at 08:04
  • I will mark your solution as accepted since its the way I started with and what worked for me, but for some reason didn't work earlier, when used it first time. – Zee Feb 10 '18 at 15:04
2
    DateTimeFormatter myDateFormatter
            = DateTimeFormatter.ofPattern("EEE, MMM d, ''yy", Locale.ENGLISH);
    long dateInSec = 1_554_321_098L;
    String utcOffsetString = "-04:00";
    ZoneOffset offset = ZoneOffset.of(utcOffsetString);
    String date = Instant.ofEpochSecond(dateInSec)
            .atOffset(offset)
            .format(myDateFormatter);
    System.out.println(date);

This prints

Wed, Apr 3, '19

The other example offset you gave, +2:00, is slightly more difficult since ZoneOffset.of requires either only hours (+2) or two-digit hours before the colon (+02:00). One solution is to fix the string before handing it to ZoneOffset:

    String utcOffsetString = "+2:00";
    utcOffsetString = utcOffsetString.replaceFirst("([-+])(\\d:\\d{2})", "$10$2");
    ZoneOffset offset = ZoneOffset.of(utcOffsetString);

The result is still Wed, Apr 3, '19. If there were already 2-digit hours in the string, replaceFirst won’t replace anything, so you just get the same string back.

If I change the offset to +08:00, I get Thu, Apr 4, '19 instead.

Edit: I frankly find the regular expression I use for fixing the offset string quite unreadable. Here’s a simpler way of fixing it:

    DateTimeFormatter offsetFormatter = DateTimeFormatter.ofPattern("O", Locale.ENGLISH);
    ZoneOffset offset = ZoneOffset.from(offsetFormatter.parse("GMT" + utcOffsetString));

Like Basil Bourque I am using java.time. See all the details in his answer.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

Not exactly what your looking for but close

String timeZone = "America/Los_Angeles"
TimeZone tz = TimeZone.getTimeZone(timeZone);
SimpleDateFormat sdf = new SimpleDateFormat("EEEEE MMMMM d hh:mm a");
sdf.setTimeZone(tz);

Date localizedTime = sdf.format(new Date());

If you keep the localization strings instead of the offsets this will work. Or you can make a map.

Lockless
  • 497
  • 1
  • 5
  • 12