从所需时区显示出正确的时间



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

例如:1504760156000它在伦敦显示

的日期时间

THU 2017年9月7日09:55:56

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

THU 9月7日2017年09:55:56 GMT 0500(巴基斯坦标准时间)

,但我想显示:

THU 2017年9月7日09:55:56 GMT 0100(英国夏季时间)

问题是:我有正确的日期和时间,但可以显示/更改时区而无需更改时间,因为时间是正确的。

更新

收到一些评论后。你没有在我的示例中得到我。

假设我在巴基斯坦,时间是1:55 PM,所以我通过应用程序向Google API询问了Google API,以告诉我伦敦的时间是什么。Google API告诉我伦敦的时间是1504760156000(上午9:55),如果我将这些毫秒转换为Date对象,它将像以下内容一样打印出来:

Date date =new Date(1504760156000)

THU 9月7日2017年09:55:56 GMT 0500(巴基斯坦标准时间)

它将根据我的本地时区进行操纵,但我希望以下结果

THU 2017年9月7日09:55:56 GMT 0100(英国夏季时间)

更新2

我在UTC中准备了时间戳,因为Google时区域API需要时间戳UTC,以秒的形式

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

Google API以下面的JSON对伦敦的json回复我。

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

根据文档:

计算本地时间

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

i总结结果 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 9月7日2017年09:55:56 GMT 0500(巴基斯坦标准时间)

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

时间戳代表以来以来经过的时间的"绝对"值。例如,您的currentTimeUTCinSeconds表示自Unix Epoch以来的秒数( 1970-01-01T00:00Z 1月1日 ST 1970年午夜在UTC 中)。Java API通常与自时代以来的毫秒数一起工作。

但是这个概念是相同的 - 这些价值是"绝对的":无论它们在哪里,它们都是相同的。如果世界不同地区(在不同时区)同时获得当前时间戳,他们都会获得相同的数字。

什么变化是,在不同的时区中,相同的数字代表不同的本地日期和时间。

例如,您正在使用的时间戳,对应于9月7日 th 2017 08:55:56 UTC,该值为1504774556(epoch以来的秒数)。同样的数字对应于伦敦的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默认时区(这是关于Date::toString()方法的行为的很好的解释)。当您执行"Date Time : "+date时,它含义调用toString()方法,结果是转换为默认时区的日期。

如果您希望以特定格式和特定的时区为特定的日期,则需要SimpleDateFormat。只需打印日期(使用System.out.println或通过记录日期)就无法使用:您无法更改日期对象本身的格式,因为Date 没有格式

我还使用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 2017年9月7日09:55:56 GMT 0100(英国夏季时间)

请注意,我不需要操纵时间戳值。我不使用Google API,但我认为他们的解释太令人困惑了,上面的代码获得了相同的结果。

在您的特定情况下,您可以做:

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

Java新日期/时间API

旧类(DateCalendarSimpleDateFormat)有很多问题和设计问题,它们被新的API替换。

在Android中,您可以使用Threeten Backport,这是Java 8的新日期/时间课程的绝佳备份。为了使它起作用,您还需要三个threetenabp(有关如何在此处使用它的更多信息)。

要从时间戳获得日期,我使用带有org.threeten.bp.ZoneIdorg.threeten.bp.Instant将其转换为时区,创建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 2017年9月7日09:55:56 GMT 0100(英国夏季时间)

在您的情况下,只需:

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

相关内容

  • 没有找到相关文章

最新更新