Java 以原始时区打印日期
假设我的设备在澳大利亚(GMT+10:00) 我从API收到了日期“2016-04-22T17:45:00+02:00” 我想在原始时区(GMT+02:00)很好地显示它 所以,我使用了SimpleDataFormat和“yyyy-MM-dd'T'HH:MM:sszzz” 但不幸的是,我找不到一种干净的方式来显示日期:Java 以原始时区打印日期,java,android,date,simpledateformat,timestamp-with-timezone,Java,Android,Date,Simpledateformat,Timestamp With Timezone,假设我的设备在澳大利亚(GMT+10:00) 我从API收到了日期“2016-04-22T17:45:00+02:00” 我想在原始时区(GMT+02:00)很好地显示它 所以,我使用了SimpleDataFormat和“yyyy-MM-dd'T'HH:MM:sszzz” 但不幸的是,我找不到一种干净的方式来显示日期: sdf.format(cal.getTime()); 使用设备时区 所以我“手动”解析了日期以提取时区,从而在日历中设置它 cal.setTimeZone(TimeZone.g
sdf.format(cal.getTime());
使用设备时区
所以我“手动”解析了日期以提取时区,从而在日历中设置它
cal.setTimeZone(TimeZone.getTimeZone("GMT" + date.substring(date.length() - 6, date.length())));
但这似乎并不奏效
我怎样才能做到这一点?因为我可以看到Date对象没有关于时区的信息。因此,有一种方法(但不是最好的方法)可以从日期字符串解析时区,并将其设置为SimpleDataFormat。比如:
String date = "2016-04-22T17:45:00+02:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ");
Calendar cal = Calendar.getInstance();
// tz is +02:00
String tz;
if (date.contains("+"))
tz = date.substring(date.indexOf("+"));
else
tz = date.substring(date.lastIndexOf("-"));
sdf.setTimeZone(TimeZone.getTimeZone("GMT" + tz));
System.out.println(sdf.format(cal.getTime()));
正如我所见,Date对象没有关于时区的信息。因此,有一种方法(但不是最好的方法)可以从日期字符串解析时区,并将其设置为SimpleDataFormat。比如:
String date = "2016-04-22T17:45:00+02:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ");
Calendar cal = Calendar.getInstance();
// tz is +02:00
String tz;
if (date.contains("+"))
tz = date.substring(date.indexOf("+"));
else
tz = date.substring(date.lastIndexOf("-"));
sdf.setTimeZone(TimeZone.getTimeZone("GMT" + tz));
System.out.println(sdf.format(cal.getTime()));
时区=偏移量+规则
在原始时区(GMT+02:00)
不,不对。文本GMT+02:00
表示一个而非时区。时区是一个偏移量加上一组处理异常的规则,如夏令时(DST)
时区以大陆/地区
的格式命名,如美洲/蒙特利尔
或亚洲/加尔各答
。始终使用。从未见过主流媒体上的3-4个缩写;这些既不是标准化的,也不是独特的
实际上,这是新的
避免旧的日期时间类
与最早版本的Java捆绑在一起的旧日期时间类被证明是设计拙劣、混乱和麻烦的。避开它们。这些类被非常成功的库及其继承者框架所取代
该框架内置于。它的大部分功能在项目中被移植到Java6和Java7,并在项目中进一步适应Android
在下一页了解更多信息
OffsetDateTime
输入字符串与UTC之间只有一个偏移量,而不是完整的偏移量。所以我们使用类来表示这种值
幸运的是,您的输入字符串是标准格式的。在解析/生成日期时间值的文本表示时,java.time类默认使用ISO 8601格式。因此,我们可以直接解析,而不用费心定义格式化模式
String input = "2016-04-22T17:45:00+02:00";
OffsetDateTime odt = OffsetDateTime.parse( input );
调用以生成相同格式的字符串
String output = odt.toString(); // ISO 8601 formatted string.
Instant
程序员不应该在这种本地日期时间思考问题。通常,您应该将业务逻辑、数据库存储和数据交换都放在一起
在java.time中,以UTC表示时间线上的一个时刻,分辨率为。我们可以从我们的OffsetDateTime
中提取一个Instant
Instant instant = odt.toInstant();
ZoneDateTime
由于处理异常(如夏令时)的规则,使用时区总比使用偏移要好
您可以通过应用来获取分区日期时间,轻松地将即时时间
或偏移日期时间
调整为时区。有关更多讨论,请参阅和关于在这些类之间转换/调整的一般主题
ZoneId zoneId_Montreal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId_Montreal );
……或者
ZonedDateTime zdt_Montreal = odt.atZoneSameInstant( zoneId_Montreal );
请注意,在应用时区时,您可能会看到一天中的时间甚至日期发生变化。可能需要根据该区域的规则进行调整,以适应或解决其他问题
您可以进一步调整到其他时区。你提到澳大利亚。那个国家有很多时区,所以你必须选择适合你(或你的用户)的时区,因为他们现在、过去或将来可能有不同的规则
ZoneId zoneId_Melbourne = ZoneId.of( "Australia/Melbourne" );
ZonedDateTime zdt_Melbourne = zdt_Montreal.withZoneSameInstant( zoneId_Melbourne );
调用ZoneDateTime::toString
时,您会注意到该方法通过在方括号中添加时区名称扩展了标准ISO 8601格式
要生成其他格式的字符串,请在堆栈溢出中搜索和的主题。Localized…的方法和a可以自动本地化格式,包括翻译人类语言日/月名称,以及遵循元素顺序、句点与逗号等文化规范
关于java.time
该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&
该项目现已启动,建议迁移到类
要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是
您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要java.sql.*
类
从哪里获得java.time类
- ,及以后
- 内置的李>
- 标准JavaAPI的一部分,带有捆绑实现
- Java9添加了一些次要功能和修复
- 及
- 大部分java.time功能都在中向后移植到Java6和Java7
-
- 更高版本的Android捆绑包实现了java.time类
- 对于早期的Android,该项目采用了ThreeTen Backport(如上所述)。看
该项目使用其他类扩展了java.time。这个项目是java.time将来可能添加的一个试验场。您可以在这里找到一些有用的类,例如、、和。时区=偏移量+规则
在原始时区(GMT+02:00)
不,不对。文本GMT+02:00
表示一个而非时区。时区是一个偏移量加上一组处理异常的规则,如夏令时(DST)
时区以大陆/地区
的格式命名,如美洲/蒙特利尔
或亚洲/加尔各答
。始终使用。从未见过主流媒体上的3-4个缩写;这些既不是标准化的,也不是独特的
实际上,这是新的
避免