从尊重时区的日历对象获取格式化字符串的最简单方法是什么?

时间:2015-11-18 20:12:53

标签: java date datetime calendar timezone

当我在线搜索“如何将joinedDiscounts.Where(disc => disc.Products.Any(prod => products.Contains(prod))) 转换为Calendar”时,我发现的所有结果都建议首先转换为String,然后转换{{1转到Date

问题是Date只是自纪元以来毫秒数的表示 - 它不尊重时区。 String以这种方式更先进。

当然,我可以调用各个Date方法来创建自己的格式化字符串,但肯定有一种更简单的方法吗?

为了说明,我写了这段代码:

Calendar

在晚上8:02从伦敦的一台机器(UTC + 0)运行此代码时,我得到了以下结果:

Calendar.get

最后一行根据日历的时区显示实际小时(马德里是UTC + 1)。现在是马德里时间下午9:02,但显然本地long currentTime = Calendar.getInstance().getTimeInMillis(); Calendar calendar = new GregorianCalendar(); calendar.setTimeZone(TimeZone.getTimeZone("Europe/Madrid")); calendar.setTimeInMillis(currentTime); System.out.println(calendar.getTime().toString()); System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime())); System.out.println(calendar.get(Calendar.HOUR_OF_DAY)); Wed Nov 18 20:02:26 UTC 2015 2015-11-18 20:02:26 21 方法都忽略了时区,因为在调用Date.toString时会删除时区信息(类似DateFormat.format })。

鉴于此,从Calendar.getTime获取格式化字符串的最佳方法是什么?尊重时区?

4 个答案:

答案 0 :(得分:3)

在SimpleDateFormat对象上设置时区,然后使用z ..

sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
sdf.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
System.out.println(sdf.format(calendar.getTime());

答案 1 :(得分:1)

有关如何在Java中处理时区的详细信息,请参阅here

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));

Calendar cal = Calendar.getInstance();
System.out.println(simpleDateFormat.format(cal.getTime()));

答案 2 :(得分:1)

java.time

虽然其他答案似乎是正确的,但更好的方法是避免完全使用java.util.Date/.Calendar。

这些旧的日期时间类已被Java 8及更高版本中内置的java.time框架所取代。新课程的灵感来自非常成功的Joda-Time框架,旨在作为其继承者,在概念上类似但重新设计。由JSR 310定义。由ThreeTen-Extra项目扩展。请参阅Tutorial

Instant

Instant表示UTC时间轴上的时刻。

Instant instant = Instant.now ( ); // Current moment in UTC.

对于给定的Calendar对象,使用Java 8中添加的方法toInstant转换为Instant

Instant instant = myCalendar.toInstant();

ZonedDateTime

您可以为ZoneId分配时区(Instant)以获得ZonedDateTime

ZoneId zoneId = ZoneId.of ( "Europe/Madrid" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant, zoneId );

日期时间值的字符串表示

转储到控制台。

System.out.println ( "instant: " + instant + " adjusted into zone: " + zoneId + " is zdt: " + zdt );

在解析/生成日期时间值的字符串表示时,默认情况下java.time类使用ISO 8601标准格式。默认情况下,除了通常的offset-from-UTC之外,还通过附加时区名称来扩展ISO 8601样式。

  

即时:2015-11-18T22:23:46.764Z调整为区域:欧洲/马德里是zdt:2015-11-18T23:23:46.764 + 01:00 [欧洲/马德里]

如果您想要ISO 8601样式但没有T,请在生成的String对象上调用.replace( "T" , "" )define your own formatter

java.time.format包可以执行确定适合特定Locale的本地化格式的工作。

Locale locale = Locale.forLanguageTag ( "es-ES" );
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime ( FormatStyle.FULL );
String output = zdt.format ( formatter.withLocale ( locale ) );
  

miércoles18de noviembre de 2015 23H38'CET

答案 3 :(得分:1)

您可以使用String.format()来避免时区问题

http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html

此示例以以下格式给出结果:" yyyy-MM-dd HH:mm:ss"

Calendar c = Calendar.getInstance();
String s = String.format("%1$tY-%1$tm-%1$td:%1$tM:%1$tS", c);
System.out.println(s);

输出:

2015-11-20:44:55