我正在开发一个从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+"×tamp="+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
旧类(Date
,Calendar
和SimpleDateFormat
)有很多问题和设计问题,它们被新的API替换。
在Android中,您可以使用Threeten Backport,这是Java 8的新日期/时间课程的绝佳备份。为了使它起作用,您还需要三个threetenabp(有关如何在此处使用它的更多信息)。
要从时间戳获得日期,我使用带有org.threeten.bp.ZoneId
的org.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));