我有一个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月份?
答案 0 :(得分:2)
服务器通常应设置为UTC,无论其物理位置如何。但永远不要依赖服务器指定的时区。始终指定任何可选时区,如下面的代码所示。 (顺便提一句Locale
)
另外,请勿将UTC与time in the United Kingdom混为一谈。英国时间有Daylight Saving Time (DST)等异常现象。将UTC视为“世界时间”。
您正在使用旧的过时类。与最早版本的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 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.UK
或Locale.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值。 Instant
表示时间轴上始终以UTC为单位的时刻。可以从任何Instant
对象中提取ZonedDateTime
对象。 Instant
类是其他类的基本构建块(OffsetDateTime
和ZonedDateTime
)。
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()));