使用所需的TimeZone

时间:2017-09-07 09:49:02

标签: android datetime google-api timezone timezone-offset

我正在开发一个从Google TimeZone API获取数据的应用程序。 简单地说,我有时间在地球上所需的地方毫秒。

例如:1504760156000它显示在伦敦的日期时间

  

Thu Sep 07 2017 09:55:56

我在UTC的TimeZone +05:00中如果我操纵1504760156000这些毫秒,它会显示如下所示的整个日期时间:

  

Thu Sep 07 2017 09:55:56 GMT + 0500(巴基斯坦标准时间)

但我想表明:

  

Thu Sep 07 2017 09:55:56 GMT + 0100(英国夏令时间)

问题的道德:我有正确的伦敦日期和时间,但能够在不更改时间的情况下显示/更改TimeZone,因为伦敦的时间是正确的。

已更新

得到一些评论后。在我的例子中,你没有让我到这里来。

假设我在巴基斯坦,时间在这里1:55 PM所以我通过我的申请向GOOGLE API询问了我在伦敦的时间。谷歌API告诉我在伦敦的时间是1504760156000(上午9:55),如果我将这些毫秒转换为Date对象,它会打印出如下所示:

Date date =new Date(1504760156000)
  

Thu Sep 07 2017 09:55:56 GMT + 0500(巴基斯坦标准时间)

它将根据我的Local TimeZone操纵它,但我想要下面的结果

  

Thu Sep 07 2017 09:55:56 GMT + 0100(英国夏令时间)

更新2

由于Google时区API需要以秒为单位的时间戳UTC,我以UTC为单位准备了以秒为单位的时间戳

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

Google API使用以下针对伦敦的JSON回复我。

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

根据文件:

  

计算当地时间

     

给定位置的本地时间是时间戳的总和   参数,以及结果中的dstOffset和rawOffset字段。

我总结结果timestamp+rawoffset+dstoffset*1000='1504760156000'(在我尝试时)

项目代码

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);

正如我所说,我在当地时区操纵结果所以当时它给了我以下结果:

  

Thu Sep 07 2017 09:55:56 GMT + 0500(巴基斯坦标准时间)

但我知道API给了我正确的时间。问题是与UTC的本地偏移。我只想将GMT+0500更改为GMT+0100

1 个答案:

答案 0 :(得分:3)

时间戳表示自纪元以来经过的时间的“绝对”值。例如,您的currentTimeUTCinSeconds表示自UTC时间为unix时期(1970-01-01T00:00Z 1月1日 st 1970年午夜时的秒数 )。 Java API通常使用自纪元以来的毫秒数。

但这个概念是一样的 - 这些价值观是“绝对的”:无论他们身在何处,他们对世界上的每个人都是一样的。如果世界不同地区的2个人(在不同的时区)同时获得当前时间戳,他们将获得相同的数字。

在不同的时区,有相同的数字代表不同的本地日期和时间。

例如,您正在使用的时间戳,对应于9月7日 th 2017 08:55:56 UTC,其值为1504774556(自纪元以来的秒数)。这个数字相当于伦敦的09:55,卡拉奇的13:55,东京的17:55,依此类推。 更改此号码会更改每个人的当地时间 - 无需操纵它。

如果您想获得代表此瞬间的java.util.Date,请执行以下操作:

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

此日期将保留值1504774556000(自纪元以来的毫秒数)。该值对应于伦敦的09:55,卡拉奇的13:55和东京的17:55。

但打印此日期会将其转换为您的JVM默认时区(here是对Date::toString()方法行为的一个很好的解释)。执行"Date Time : "+date时,它会调用toString()方法,结果是将日期转换为默认时区。

如果您想要特定格式和特定​​时区的日期,则需要SimpleDateFormat。只打印日期(使用System.out.println或记录日期)将无效:您无法更改日期对象本身的格式,因为Date has no format

我还使用java.util.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));

输出将是:

  

Thu Sep 07 2017 09:55:56 GMT + 0100(英国夏令时间)

请注意,我不需要操纵时间戳值。我不使用谷歌API,但我认为他们的解释太混乱了,上面的代码实现了相同的结果,并没有更少的复杂性。

在您的具体情况下,您可以:

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

Java新日期/时间API

旧类(DateCalendarSimpleDateFormat)有lots of problemsdesign issues,它们将被新API取代。< / p>

在Android中,您可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端。为了使其有效,您还需要ThreeTenABP(更多关于如何使用它here)。

要从时间戳获取日期,我使用org.threeten.bp.Instantorg.threeten.bp.ZoneId将其转换为时区,创建org.threeten.bp.ZonedDateTime。然后我用org.threeten.bp.format.DateTimeFormatter格式化它:

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));

输出相同:

  

Thu Sep 07 2017 09:55:56 GMT + 0100(英国夏令时间)

在你的情况下,只需:

date1.setText("Date Time : "+fmt.format(z));