获取启用时区的DateTime实例的字母数字月份值

时间:2016-06-21 16:22:10

标签: java datetime time timezone dst

我有一个linux服务器,它设置为使用UTC时间,因为它位于英国。我有一段java代码,它运行在6月最后一天的纽约时间22:00。这意味着在英国,它将是下个月的第二天。

我想从DateTime实例中检索字母数字月份(1月,2月等),但是要查看America / New_York日期。目前,下面的代码给了我7月份的英国月份,但我希望它能在6月份将DateTime设置为America / New_York。

DateFormat fullMonthFormat = new SimpleDateFormat("MMMM");
DateTime dt1 = new DateTime();
dt1 = dt1.withZone(DateTimeZone.forID("America/New_York"));
System.out.println(fullMonthFormat.format(dt1.toDate()));

例如。如果我是在纽约时间30/06/2016 22:00进行此操作,println声明将给我7月份的价值。如何获得正确的月份文本,应该是6月份?

3 个答案:

答案 0 :(得分:2)

UTC 英国时间

服务器通常应设置为UTC,无论其物理位置如何。但永远不要依赖服务器指定的时区。始终指定任何可选时区,如下面的代码所示。 (顺便提一句Locale

另外,请勿将UTCtime in the United Kingdom混为一谈。英国时间有Daylight Saving Time (DST)等异常现象。将UTC视为“世界时间”。

java.time

您正在使用旧的过时类。与最早版本的Java捆绑在一起的日期时间类已被证明设计糟糕,令人困惑且麻烦。避免它们。

java.time框架内置于Java 8及更高版本中。见Oracle Tutorial。这些课程的灵感来自非常成功的Joda-Time库。 java.time的大部分功能是back-ported to Jave 6 & 7,还有adapted to Android

时区

我们必须跟踪时区。 ZoneId类表示用于处理DST(例如DST)等异常的时区(offset-from-UTC 加上规则)。指定proper time zone name从不主流媒体(例如EST)中常见的3-4个字母代码。

ZoneId zoneId_New_York = ZoneId.of ( "America/New_York" );
ZoneId zoneId_London = ZoneId.of ( "Europe/London" );

纽约地区

ZonedDateTime类代表时间轴上的一个时刻,分辨率为纳秒,并为指定的时区提供wall-clock time

ZonedDateTime zdt_NewYork = ZonedDateTime.of ( 2016 , 6 , 30 , 22 , 0 , 0 , 0 , zoneId_New_York );

Month enum代表一年中的每个月。

Month month_NewYork = Month.from ( zdt_NewYork );

Month枚举提供了方便的方法,例如告诉您月份编号(1-12)。

int month_NewYork_number = month_NewYork.getValue (); // 1-12 January-December.

Month枚举甚至可以通过Locale描述的人类语言和文化规范来本地化月份名称。在这里,我使用locale of Québec生成法语值只是为了明确行为,但在您的特定情况下,可能会使用Locale.UKLocale.US

String month_NewYork_name = month_NewYork.getDisplayName ( TextStyle.FULL , Locale.CANADA_FRENCH );

转储控制台。请注意月份名称juin(法语为'六月')和月份#6。

System.out.println ( "zdt_NewYork: " + zdt_NewYork + " | month #: " + month_NewYork_number + " | name: " + month_NewYork_name );
  

zdt_NewYork:2016-06-30T22:00-04:00 [America / New_York] |月#:6 |名称:juin

伦敦地区

接下来,我们将ZonedDateTime调整为另一个时区。 java.time类使用immutable objects,因此我们实际上生成了一个新的不同对象,而不是更改/编辑(“改变”)原始对象。

ZonedDateTime zdt_London = zdt_NewYork.withZoneSameInstant ( zoneId_London );
Month month_London = Month.from ( zdt_London );
int month_London_number = month_London.getValue (); // 1-12 January-December.
String month_London_name = month_London.getDisplayName ( TextStyle.FULL , Locale.CANADA_FRENCH );

转储到控制台。请注意juillet(法语为' 7月和#39;)和月份#7的输出。

System.out.println ( "zdt_London: " + zdt_London + " | month #: " + month_London_number + " | name: " + month_London_name );
  

zdt_London:2016-07-01T03:00 + 01:00 [欧洲/伦敦] |月#:7 |名称:juillet

UTC区域

最后,我们检查UTC值。 Instant表示时间轴上始终以UTC为单位的时刻。可以从任何Instant对象中提取ZonedDateTime对象。 Instant类是其他类的基本构建块(OffsetDateTimeZonedDateTime)。

Instant instant = zdt_London.toInstant ();

转储到控制台。请注意,输出与伦敦时间相同。夏季伦敦遭受DST,而UTC仍保持稳定。所以我们在这里看到上午2点的UTC而不是凌晨3点的Europe/London

System.out.println ( "UTC… instant: " + instant );
  

UTC ...时间:2016-07-01T02:00:00Z

请记住,所有这三个日期时间值(zdt_NewYork,zdt_London和instant)都代表时间轴上非常相同的同时点,这是历史上的同一时刻。每个都是相同的时刻,但通过各种挂钟时间镜头观看。

答案 1 :(得分:1)

您也可以使用java.util.Date来实现这一目标:

SimpleDateFormat sdf = new SimpleDateFormat("MMMM");
Date datetime = new Date();
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println(sdf.format(datetime));

希望这有帮助。

答案 2 :(得分:0)

您需要将time zone设置为fullMonthFormat,因为您需要纽约月份。 如果要将特定时区的任何日期格式化为需要将特定时区设置为DateFormat对象,则DateFormat使用本地时间(UTC)。

所以看起来应该是这样的:

DateFormat fullMonthFormat = new SimpleDateFormat("MMMM");
DateTime dt1 = new DateTime();
DateTimeZone dtz = DateTimeZone.forID("America/New_York");
dt1 = dt1.withZone(dtz);
fullMonthFormat.setTimeZone(dtz.toTimeZone());
System.out.println(fullMonthFormat.format(dt1.toDate()));