Java 用 Joda 时间将军用时间转换为民用时间

Java Convert military hour to civilian hour with Joda time

我正在尝试转换一个 int(代表军事时间)并将其转换为民用时间。例如,如果我有小时“13”,我想将其转换为“1:00 pm”。这是我一直在尝试的:

private DateTimeFormatter hourFormat = DateTimeFormat.forPattern("hh:mm a");
private DateTimeFormatter dateFormat = DateTimeFormat.forPattern("YYYY-MM-dd");

int hour = 8;
DateTime fullDate = new DateTime();
 String date = dateFormat.print(fullDate) + " " + Integer.toString(hour) + ":00";
String civilianTime = hourFormat.parseDateTime(date).toString();

Logcat:

java.lang.IllegalArgumentException: Invalid format: "2016-01-27 8:00" is malformed at "16-01-27 8:00"
at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:945)

Joda 不允许我重新格式化小时,我收到“8:00 太短”类型的错误,所以这就是为什么我包含日期并将日期和时间组合成一个字符串,即使我不需要日期。我也试过在那里使用时区组件,但我得到了同样的错误。仅供背景参考:int "hour" 来自数据库查询的时间戳(UTC w/时区偏移量),该查询吐出我需要的小时列表。所以我回来的时间已经考虑了时区。

本质上,我试图从一天中的 "HH" 小时 (0-23) 到半天中的 "hh:mm a" 时钟小时 (1-12)。我假设有时 "HH" 只是 "H" 因为从数据库查询到应用程序时前导零被删除。我用 hour = 8 和 hour = 10 试过这个,结果错误相同。

感谢使用 LocalTime 的评论之一,这就完成了:

private DateTimeFormatter hourFormat = DateTimeFormat.forPattern("h:mm a");   
int hour = 8;
String ltime = new LocalTime(hour,0).toString(hourFormat);

格式模式中,Joda-time的DateTimeFormatclass表示使用:

  • h(小写)表示半天的时钟时间(1~12)
  • H(大写)表示一天中的小时 (0~23)

如果要为单个数字值填充前导 0(零),请使用双精度 hh。例如获取 08:00 而不是 8:00。解析时,接受任意数量的数字。

tl;博士

使用 java.time 而不是 Joda-Time。

LocalTime.of( 13 , 0 )
         .format( 
             DateTimeFormatter.ofLocalizedTime( FormatStyle.SHORT )
                              .withLocale( Locale.US ) 
         )

1:00 PM

看到这个code run live at IdeOne.com

……或者……

ZonedDateTime.of(
    LocalDate.now( ZoneId.of( "Pacific/Auckland" ) ) ,  // Get today’s date at this moment in this time zone.
    LocalTime.of( 13 , 0 ) ,                            // Specify the time-of-day given to us. In this example `13` for 1 PM is given to us.
    ZoneId.of( "Pacific/Auckland" )                     // Specify the time zone giving the context for this date-time. 
).format(                                               // Generate a string representing the value of this date-time object.
     DateTimeFormatter.ofLocalizedDateTime( FormatStyle.SHORT )
                      .withLocale( Locale.US )          // Localize using the language and cultural norms of the United States.
 )

5/4/17 1:00 PM

更新

Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. See Tutorial by Oracle.

使用java.time

LocalTime and LocalDate classes represent each part of a date-time without any offset-from-UTC 也不是时区。

int hour = 13 ;  // 24-hour clock, 0-23. So `13` is 1 PM. 
LocalTime lt = LocalTime.of( hour , 0 ); // ( hours , minutes )

lt.toString(): 13:00

让 java.time 为您本地化。

要本地化,请指定:

  • FormatStyle 确定字符串的长度或缩写。
  • Locale 以确定 (a) 用于翻译日期名称、月份名称等的人类语言,以及 (b) 决定缩写、大写问题的文化规范、标点符号、分隔符等。

    DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime( FormatStyle.SHORT ).withLocale( Locale.US ) ; 字符串输出 = lt.format( f );

output: 1:00 PM

时区对于确定日期至关重要。对于任何给定时刻,日期在全球范围内因地区而异。例如,Paris France is a new day while still “yesterday” in Montréal Québec.

午夜后几分钟

指定 proper time zone name in the format of continent/region, such as America/Montreal, Africa/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们 不是 真正的时区,没有标准化,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate ld = LocalDate.now( z );

ld.toString(): 2017-01-23

为了到达时间轴上的特定点,我们应用时区(ZoneId 对象)以获得 ZonedDateTime.

ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;  // ( LocalDate , LocalTime , ZoneId )

zdt.toString(): 2017-01-23T13:00:00-05:00[America/Montreal]

生成所需格式的字符串。如上所示,让 java.time 为您本地化。

DateTimeFormatter f2 = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.SHORT ).withLocale( Locale.US ) ;
String output2 = zdt.format( f2 );

5/4/17 1:00 PM

看到这个code run live at IdeOne.com

不是真正的“军事时间”

顺便说一下,术语“military time” in referring to the 24-hour clock 主要是美国现象,因为美国是 12 小时制占主导地位的罕见地方之一。

世界各地的其他人通常同时使用这两种时钟,在日常事务中使用 12 小时制,在火车时刻表等重要事务中使用 24 小时制。根据我的经验,这是一个更明智的做法。


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

在哪里获取java.time类?