7

I'm developing an application which takes data from Google TimeZone API. Simply I have time in milliseconds of desired place on Earth.

For Example : 1504760156000 it's showing Date time In London which is

Thu Sep 07 2017 09:55:56

As I'm in TimeZone +05:00 from UTC if I manipulate 1504760156000 these milliseconds it will show me whole date time like below:

Thu Sep 07 2017 09:55:56 GMT+0500 (Pakistan Standard Time)

but I want to show:

Thu Sep 07 2017 09:55:56 GMT+0100 (British Summer Time)

The problem is: I have correct date and time for London but enable to show/change TimeZone without changing Time because Time is correct according to London.

UPDATED

After getting some comments. You are not getting me here in my example.

Suppose I am in Pakistan and Time here is 1:55 PM so I asked GOOGLE API via my application to tell me whats the time in London at moment. Google API tell me time in London is 1504760156000 (9:55 AM) in milliseconds if I convert these milliseconds to Date Object it will print out like below:

Date date =new Date(1504760156000)

Thu Sep 07 2017 09:55:56 GMT+0500 (Pakistan Standard Time)

It will manipulate it according to my Local TimeZone but I want results like below

Thu Sep 07 2017 09:55:56 GMT+0100 (British Summer Time)

Updated 2

I prepared timestamp in seconds in UTC as Google Time Zone API needed timestamp UTC in form of seconds

"https://maps.googleapis.com/maps/api/timezone/json?location="+Latitude +","+Longitude+"&timestamp="+currentTimeUTCinSeonds+"&key="API KEY"

Google API respond me with below JSON against London.

{
    "dstOffset" : 3600,   
    "rawOffset" : 0,  
    "status" : "OK",  
    "timeZoneId" : "Europe/London",  
    "timeZoneName" : "British Summer Time"
}

According to Docs:

Calculating the Local Time

The local time of a given location is the sum of the timestamp parameter, and the dstOffset and rawOffset fields from the result.

I Sum up result timestamp+rawoffset+dstoffset*1000='1504760156000' (at moment when I tried it)

Code from Project

Long ultimateTime=((Long.parseLong(timeObject1.getDstOffset())*1000)+(Long.parseLong(timeObject1.getRawOffset())*1000)+timestamp*1000);
                    timeObject1.setTimestamp(ultimateTime);  //its Sime POJO object to save current time of queried Location 
                    Date date=new Date(ultimateTime);
                    date1.setText("Date Time : "+date);

As I said I'm manipulating result in Local Time Zone so it gave me below result at that time:

Thu Sep 07 2017 09:55:56 GMT+0500 (Pakistan Standard Time)

But I knew API gave me correct time. The problem is Local offset from UTC . I just want to change GMT+0500 to GMT+0100

Zaid Mirza
  • 3,540
  • 2
  • 24
  • 40
  • Probably [this](https://stackoverflow.com/a/14854411/6503228) answer would help you. – devgun Sep 07 '17 at 10:32
  • @kcg no,You didn't get my problem. I want get result in desired TimeZone, not in my own – Zaid Mirza Sep 07 '17 at 10:57
  • But timestamp 1504760156000 is equivalent to 09:55 in Pakistan and 05:55 in London. Showing it as 09:55 in London isn't correct. –  Sep 07 '17 at 11:15
  • @Hugo,no, timestamp 1504760156000 is London time which I took from Google API but as Im in Pakistan if I manipulate it on my local system it will get default +5 TimeZone but want to show London Time Zone being in Pakistan. Read my question carefuly – Zaid Mirza Sep 07 '17 at 11:19
  • @Zaid Mizra , then you better get pakistan local time and convert it to london time ..... – Omar Dhanish Sep 07 '17 at 11:20
  • @OmarDanisha why should I convert it to London as Google API already giving me correct time for London. I just want my local system to Ignore my local timezone and show London Time Zone on being manipulate in Pakstan. – Zaid Mirza Sep 07 '17 at 11:23
  • @ZaidMirza 1504760156000 is **not** London time. It's the number of milliseconds since `1970-01-01T00:00Z` (January 1st 1970 at midnight in **UTC**). It's a timestamp (an instant, a point in the timeline) and this value is the same for everyone in the world. This same value can correspond to different local dates and times depending on the timezone you are. Take a look at [this](https://ideone.com/8d5e84), note how the same instant corresponds to a different time in each timezone. You can also convert this to utc in https://currentmillis.com –  Sep 07 '17 at 11:26
  • @Hugo, You are looking different perceptive, '1504760156000' is not in UTC. its UTC+offset of London Means time is correct. I have updated my question Please have a look at example – Zaid Mirza Sep 07 '17 at 11:33
  • @ZaidMirza Once again: 1504760156000 is just **the number of milliseconds since `1970-01-01T00:00Z`**, nothing more. This same value corresponds to 04:55 in UTC, 05:55 in London, 09:55 in Pakistan, 13:55 in Tokyo and so on. Maybe if you include the code that gets this from the API we can have more clues about what's happening. –  Sep 07 '17 at 11:40
  • @Hugo did you read my updated Example?I said Suppose its 1:55 PM In Pakistan while UTC is 8:55 AM and as London is +1 from UTC so Google API gave me offset+timestamp*1000='1504760156000' which is 9:55 AM at that moment in London. – Zaid Mirza Sep 07 '17 at 11:46
  • @Hugo 1504760156000 manipulate this number in your local Zone it will show you 9:55 AM with your Time Zone. Problem is I want to ignore LocalTime Zone. For Example your friend from Dubai said hey Hugo its `11:30` here in Dubai lemme give you its milliseconds form he will convert it and tell you '14067777157000' its conversion of current time of dubai in millis. Then you do this on your machine `Date date=new Date (14067777157000)` you will get 11:30 GMT within your TimeZone. but you want to show user Dubai TimeZone with `11:30`.. I hope you got it – Zaid Mirza Sep 07 '17 at 12:07
  • Does the API return 1504760156000 or you get this number by manipulating the results? Because this timestamp doesn't correspond to 09:55 in London. Either the API is wrong or you're misusing it. And the date you create is a `java.util.Date`? Maybe if you include the code that calls the API and creates the date, we can have a better picture of what's going on –  Sep 07 '17 at 12:41
  • And this number 1504760156000 in my timezone (America/Sao_Paulo) gives 01:55 - https://ideone.com/izmJ8d –  Sep 07 '17 at 12:43
  • @Hugo yes this is after manipulation API result. thats Why I said time is correct when I query the API at 13:55 Pak Time. wait lemme update question – Zaid Mirza Sep 07 '17 at 12:44
  • @Hugo check update 2 – Zaid Mirza Sep 07 '17 at 12:58
  • @Hugo its giving 01:55 because you are checking current time in London. and Im explaining based on my static example. When I actually perform query it was 13:55 in Pak, 8:55 in UTC and 9:55 in London – Zaid Mirza Sep 07 '17 at 13:00
  • What was the value of `currentTimeUTCinSeonds`? –  Sep 07 '17 at 13:02
  • @Hugo value of it is Convert 7 Sep 2017 08:55 AM (UTC time) to Seconds – Zaid Mirza Sep 07 '17 at 13:04

1 Answers1

6

Timestamps represent an "absolute" value of a time elapsed since epoch. Your currentTimeUTCinSeconds, for example, represent the number of seconds since unix epoch (which is 1970-01-01T00:00Z, or January 1st 1970 at midnight in UTC). Java API's usually work with the number of milliseconds since epoch.

But the concept is the same - those values are "absolute": they are the same for everyone in the world, no matter where they are. If 2 people in different parts of the world (in different timezones) get the current timestamp at the same time, they'll all get the same number.

What changes is that, in different timezones, this same number represents a different local date and time.

For example, the timestamp you're using, that corresponds to Sep 7th 2017 08:55:56 UTC, which value is 1504774556 (the number of seconds since epoch). This same number corresponds to 09:55 in London, 13:55 in Karachi, 17:55 in Tokyo and so on. Changing this number will change the local times for everyone - there's no need to manipulate it.

If you want to get a java.util.Date that represents this instant, just do:

int currentTimeUTCinSeconds = 1504774556;
// cast to long to not lose precision
Date date = new Date((long) currentTimeUTCinSeconds * 1000);

This date will keep the value 1504774556000 (the number of milliseconds since epoch). This value corresponds to 09:55 in London, 13:55 in Karachi and 17:55 in Tokyo.

But printing this date will convert it to your JVM default timezone (here is a good explanation about the behaviour of Date::toString() method). When you do "Date Time : "+date, it implicity calls toString() method, and the result is the date converted to your default timezone.

If you want the date in a specific format and in a specific timezone, you'll need a SimpleDateFormat. Just printing the date (with System.out.println or by logging it) won't work: you can't change the format of the date object itself, because a Date has no format.

I also use a java.util.Locale to specify that the month and day of week must be in English. If you don't specify a locale, it'll use the system default, and it's not guaranteed to always be English (and this can be changed, even at runtime, so it's better to always specify a locale):

// use the same format, use English for month and day of week
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'Z (zzzz)", Locale.ENGLISH);
// set the timezone I want
sdf.setTimeZone(TimeZone.getTimeZone("Europe/London"));
// format the date
System.out.println(sdf.format(date));

The output will be:

Thu Sep 07 2017 09:55:56 GMT+0100 (British Summer Time)

Note that I don't need to manipulate the timestamp value. I don't use the google API, but I think their explanation is too confusing and the code above achieve the same results with less complication.

In your specific case, you can do:

date1.setText("Date Time : "+sdf.format(date));

Java new Date/Time API

The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.

In Android you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To make it work, you'll also need the ThreeTenABP (more on how to use it here).

To get a date from a timestamp, I use a org.threeten.bp.Instant with a org.threeten.bp.ZoneId to convert it to a timezone, creating a org.threeten.bp.ZonedDateTime. Then I use a org.threeten.bp.format.DateTimeFormatter to format it:

int currentTimeUTCinSeconds = 1504774556;
// get the date in London from the timestamp
ZonedDateTime z = Instant.ofEpochSecond(currentTimeUTCinSeconds).atZone(ZoneId.of("Europe/London"));
// format it
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("EEE MMM dd yyyy HH:mm:ss 'GMT'XX (zzzz)", Locale.ENGLISH);
System.out.println(fmt.format(z));

The output is the same:

Thu Sep 07 2017 09:55:56 GMT+0100 (British Summer Time)

In your case, just do:

date1.setText("Date Time : "+fmt.format(z));
  • now you got me. It is just printing issue. What if I dont Specify Locale.English? why You specified it? – Zaid Mirza Sep 07 '17 at 13:53
  • 3
    @ZaidMirza If you don't specify a locale, it'll use the JVM's default (in the JVM I'm using, for example, the default is Portuguese), and this affects the names of the month, day of week and even the timezone name. Just make a test without the locale and see what you get. But if you want the output in a specific language, it's better to use a specific locale. If I use the default locale in my JVM, the output is in Portuguese: `Qui set 07 2017 09:55:56 GMT+0100 (Fuso horário de verão da Grã-Bretanha)` –  Sep 07 '17 at 14:25
  • Thank You Sir, You helped me a lot. You clear me more about my concept. – Zaid Mirza Sep 08 '17 at 12:27
  • This was really helpful! Thanks! – Andres Gardiol May 18 '21 at 15:18