如何在Java中更改String.format()中%tZ使用的时区?

时间:2017-06-21 12:49:57

标签: java datetime time date-format

在以下代码段中,我想更改String.format()

使用的时区
long mls = System.currentTimeMillis();
String time = String.format("%tT %tZ", mls, mls);
System.out.println("TIME: " + time + " \n");

3 个答案:

答案 0 :(得分:3)

如果您查看javadoc,您会看到Z模式使用您的JVM default timezone

  

'Z'表示时区缩写的字符串。此值将根据夏令时的需要进行调整。对于 long ,Long和Date,使用的时区是此Java虚拟机实例的默认时区。 Formatter的语言环境将取代参数的语言环境(如果有的话)。

因此,最简单的方法是使用java.util.TimeZone类更改默认时区。一些随机时区的示例:

TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
long mls = System.currentTimeMillis();
String time = String.format("%tT %tZ", mls, mls);
System.out.println("TIME: " + time + " \n");

输出:

  

时间:英国夏令时14:03:54

新Java日期/时间API

我认为这不是格式化日期的最佳方式,特别是因为它取决于系统的默认时区(可以在运行时更改并破坏您的代码),并且它使用旧的API({{1} } class)。

现在,Java有了一个新的API,可以让事情变得更容易。

如果您使用的是 Java 8 ,请考虑使用new java.time API。它更容易,less bugged and less error-prone than the old APIs

如果您使用的是 Java< = 7 ,则可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端。对于 Android ,有ThreeTenABP(更多关于如何使用它here)。

以下代码适用于两者。 唯一的区别是包名称(在Java 8中为TimeZone,在ThreeTen Backport(或Android的ThreeTenABP)中为java.time),但类和方法名称是相同的

如您只想要时间(小时/分钟/秒),您可以使用org.threeten.bp类和LocalTime来自定义输出格式。我还使用了DateTimeFormatter类来指定时区:

ZoneId

输出结果为:

  

14时09分22秒

请注意,我使用// get current time in London LocalTime now = LocalTime.now(ZoneId.of("Europe/London")); // formatter for HH:mm:ss output DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm:ss"); System.out.println(fmt.format(now)); // 14:09:22 作为时区。更喜欢使用这些长名称,因为短名称(如Europe/LondonCST)是ambiguous and not standard

您可以使用IST获取所有可用时区的列表。

如果要输出时区短名称(如模式ZoneId.getAvailableZoneIds()那样),则必须使用%tZ类,因为ZonedDateTime没有时区信息它:

LocalTime

在这种情况下,输出将是:

  

14:09:22 BST

您可以查看DateTimeFormatter javadoc以查看所有可能的格式。

答案 1 :(得分:3)

在Java中使用时区格式化时间的方法有很多种,String.format()是最不灵活的。

下面的所有6条建议都假设您有一个long毫秒值(mls),并且需要格式化该时间。所有6条建议的输出都是相同的。

如果坚持使用String.format(),您可以通过各种方式控制时区:

  • 由于longLongjava.util.Date参数将使用JVM的默认时区,您可以使用TimeZone.setDefault(TimeZone zone)进行更改,但是通常是一个坏主意,所以我强烈反对你这样做。

  • 由于Calendar参数具有时区,因此您可以更改long毫秒参数以使用该参数:

    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Pacific/Honolulu"));
    cal.setTimeInMillis(mls);
    String time = String.format("%tT %tZ", cal, cal);
    
  • 在Java 8中,您还可以使用新的java.time对象:

    ZonedDateTime zdt = Instant.ofEpochMilli(mls).atZone(ZoneId.of("Pacific/Honolulu"));
    String time = String.format("%tT %tZ", zdt, zdt);
    

如果您不必使用String.format(),则应在Java 8中使用新的java.time对象。如果在Java 6或7上,您可以添加ThreeTen Backport jar:< / p>

  • 使用ZonedDateTime指定时区:

    ZonedDateTime zdt = Instant.ofEpochMilli(mls).atZone(ZoneId.of("Pacific/Honolulu"));
    String time = zdt.format(DateTimeFormatter.ofPattern("HH:mm:ss z"));
    
  • DateTimeFormatter中指定时区:

    DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm:ss z")
                                             .withZone(ZoneId.of("Pacific/Honolulu"));
    String time = fmt.format(Instant.ofEpochMilli(mls));
    

如果您使用的是Java 8之前的版本,并且不想为ThreeTen Backport添加额外的jar,则可以执行以下操作:

  • 使用SimpleDateFormat

    SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss z");
    fmt.setTimeZone(TimeZone.getTimeZone("Pacific/Honolulu"));
    String time = fmt.format(mls);
    

注意:上面的所有代码都使用了檀香山时间,因为这是我想要所在的时区。

答案 2 :(得分:1)

Formatter类,String.format()和其他人使用的格式字符串接受日期和时间的丰富类型。例如:

    ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Europe/Lisbon"));
    String time = String.format("%tT %<tZ", zdt);
    System.out.println("TIME: " + time + " \n");

输出:

TIME: 18:33:05 WEST 

我认为这是西欧夏令时的西部。

并不是说你真的想要输出四个字母的时区缩写,现在我们就是这样。这些缩写词往往含糊不清,不规范。对于时区,大写Z我更倾向于使用小写z作为UTC的偏移量。他们永远不会模棱两可。不幸的是,欧洲/里斯本这样的长时区名称似乎不是一个选择。为此,您可以使用DateTimeFormatter

来自文档:“日期/时间 - 可能会应用于能够对日期或时间进行编码的Java类型:longLong,{{1 }},CalendarDate“。最后一个是由大多数现代日期和时间类实现的界面,包括TemporalAccessorDayOfWeekHijrahDateHijrahEraInstant,{{1} },IsoEraJapaneseDateJapaneseEraLocalDateLocalDateTimeLocalTimeMinguoDateMinguoEraMonthMonthDayOffsetDateTimeOffsetTimeThaiBuddhistDateThaiBuddhistEraYearYearMonth

我在格式字符串中使用ZonedDateTime再次使用相同的参数,因此我不必将ZoneOffset两次传递给<