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

Get the alphanumeric month value for a timezone enabled DateTime instance

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

我想从 DateTime 实例中检索字母数字月份(一月、二月等),但要检索 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 语句将给我值 'July'。我怎样才能获得正确的月份文本,应该是六月?

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

所以它应该是这样的:

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()));

您也可以使用 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));

希望对您有所帮助。

UTC 是不是英国时间

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

此外,不要将 UTC 英国时间 混为一谈。英国时间存在 夏令时 (DST) 等异常现象。将 UTC 视为“世界时间”。

java.time

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

java.time framework is built into Java 8 and later. See Oracle Tutorial. These classes were inspired by the highly successful Joda-Time library. Much of the java.time functionality is back-ported to Jave 6 & 7 and further adapted to Android

时区

我们必须跟踪时区。 ZoneId class represents a time zone (an offset-from-UTC plus rules for handling anomalies such as DST). Specify a proper time zone name从来没有EST等主流媒体常见的3-4字母代码。

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

纽约地区

指定时区的 ZonedDateTime class represents a moment on the timeline with a resolution of nanoseconds and with a 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 enum can even localize the name of the month by human language and cultural norms described by a Locale. Here I use the locale of Québec to generate French values just to make clear the behavior, but in your particular case would likely use Locale.UK or Locale.US.

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

转储控制台。请注意月份名称 juin(法语为 'June')和月份 #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] | month #: 6 | name: juin

伦敦区

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

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 的输出(法语表示 'July')和月份 # 7.

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

zdt_London: 2016-07-01T03:00+01:00[Europe/London] | month #: 7 | name: juillet

UTC 时区

最后,我们检查 UTC 值。 Instant represents a moment on the timeline always in UTC. An Instant object can be extracted from any ZonedDateTime object. The Instant class is the basic building block of other classes (OffsetDateTimeZonedDateTime).

Instant instant = zdt_London.toInstant ();

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

凌晨 3 点
System.out.println ( "UTC… instant: " + instant );

UTC… instant: 2016-07-01T02:00:00Z

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