我正在创建一个Calendar
实例(当前时间),然后设置小时分钟和上午/下午
Calendar now = Calendar.getInstance();
now.set(Calendar.HOUR,12);
now.set(Calendar.MINUTE,0);
now.set(Calendar.AM_PM,1);
然后,如果我尝试从现在的Calendar实例中获取am / pm,它将错误地始终设置为am并提前1天。这似乎只发生在12小时而没有其他小时。这是什么问题?我设置它们的顺序是重要还是在第12小时的情况下,我应该使用24小时格式来设置'now'实例吗? 是的我应该提到,这是在Android上。
答案 0 :(得分:17)
这是因为每天的一半都是从小时零到小时11结束。数学上讲,没有第12个小时(即使我们在现实生活中一直使用它)。所以你要设定的是在PM期间的小时零,所以:
now.set(Calendar.HOUR, 0);
now.set(Calendar.MINUTE,0);
now.set(Calendar.AM_PM, Calendar.PM);
通过将小时设置为12,您可以告诉日历(对或错,您必须要求Oracle工程师)将其设置为PM时段的第12个小时,该时段最终为0小时。第二天上午。
在半天时间内只有12个小时,而且这个数字是零,所以在数学上说,没有第12个小时。它是零。这有点直观,因为我们习惯说它是12:30,而不是0:30。
答案 1 :(得分:1)
对我来说更好的答案是AndroidDev
How to set time to 24 hour format in Calendar 她说 使用Calendar.HOUR_OF_DAY 所以它应该是now.set(Calendar.HOUR_OF_DAY,0);
答案 2 :(得分:0)
上午12点。
LocalTime.MIN.with ( ChronoField.CLOCK_HOUR_OF_AMPM , 12 )
.with ( ChronoField.AMPM_OF_DAY , 0 );
下午12点。
LocalTime.MIN.with ( ChronoField.CLOCK_HOUR_OF_AMPM , 12 )
.with ( ChronoField.AMPM_OF_DAY , 1 );
你正在使用现在遗留下来的麻烦的旧日期时间类,在Java 8及更高版本的java.time中取代,在adaptation的java.time back-port取代的Android中。
LocalTime
尽可能使用您在问题中提到的24小时制。 java.time中的LocalTime
类执行此操作,使用小时0-23表示每小时。
如果被迫使用12小时制,一种方法是构造字符串,然后让LocalTime
解析它们。
String input = hour + ":" + minute + " " + ( isAM ? "AM" : "PM" ) ; // Ex: 7:53 AM
DateTimeFormatter
定义格式模式以匹配DateTimeFormatter
类。
DateTimeFormatter f = DateTimeFormatter.ofPattern( "h:m a" );
LocalTime lt = LocalTime.parse( input , f );
如果您只需要时间,那么就完成了。
ZonedDateTime
如果您需要将此时间与日期相关联,请创建LocalDate
对象,使用ZoneId
指定预期时区的上下文,然后摇动以混合为ZonedDateTime
。如果您的时间在该日期无效,则java.time会根据需要进行调整。一定要学习JavaDoc来理解这种调整的行为,看看你是否同意。
LocalDate ld = LocalDate.of( 2017 , Month.MARCH , 4 );
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );
TemporalField
TemporalField
接口提供了可以更改日期时间值的类。因为java.time使用immutable objects,所以我们基于另一个对象实例化一个新对象,但是改变了一个特定的字段。 ChronoField
枚举提供了一些方便的实现。
HOUR_OF_AMPM
对象让我们指定1-12而不是0-23的小时计数。将其与AMPM_OF_DAY
组合以指定1-12小时是针对早晨(AM = 0)还是晚上(PM = 1)。为方便起见,您可以将这些调用链接起来。
让我们尝试AM和PM,在最后一个参数中传递零或一个。第一个上午,传递0
。
LocalTime fiveAm =
LocalTime.MIN.with ( ChronoField.HOUR_OF_AMPM , 5 )
.withMinute ( 23 )
.with ( ChronoField.AMPM_OF_DAY , 0 ); // 05:23
和PM,传递1
。
LocalTime fivePm =
LocalTime.MIN.with ( ChronoField.HOUR_OF_AMPM , 5 )
.withMinute ( 23 )
.with ( ChronoField.AMPM_OF_DAY , 1 ); // 17:23
转储到控制台。
System.out.println ( "fiveAm.toString(): " + fiveAm );
System.out.println ( "fivePm.toString(): " + fivePm );
fiveAm.toString():05:23
fivePm.toString():17:23
上面的代码使用的HOUR_OF_AMPM
计算小时数0-11。让我们尝试零看看效果。
LocalTime zeroAm =
LocalTime.MIN.with ( ChronoField.HOUR_OF_AMPM , 0 )
.withMinute ( 23 )
.with ( ChronoField.AMPM_OF_DAY , 0 );
LocalTime zeroPm =
LocalTime.MIN.with ( ChronoField.HOUR_OF_AMPM , 0 )
.withMinute ( 23 )
.with ( ChronoField.AMPM_OF_DAY , 1 );
转储到控制台。
System.out.println ( "zeroAm.toString(): " + zeroAm );
System.out.println ( "zeroPm.toString(): " + zeroPm );
zeroAm.toString():00:23
zeroPm.toString():12:23
但问题想要使用12
,这意味着我们将12小时制的小时计为1-12而不是0-11。 java.time类也适用于此。只需从使用HOUR_OF_AMPM
切换到CLOCK_HOUR_OF_AMPM
。
LocalTime twelveAm =
LocalTime.MIN.with ( ChronoField.CLOCK_HOUR_OF_AMPM , 12 )
.withMinute ( 23 )
.with ( ChronoField.AMPM_OF_DAY , 0 );
LocalTime twelvePm =
LocalTime.MIN.with ( ChronoField.CLOCK_HOUR_OF_AMPM , 12 )
.withMinute ( 23 )
.with ( ChronoField.AMPM_OF_DAY , 1 );
转储到控制台。
System.out.println ( "twelveAm.toString(): " + twelveAm );
System.out.println ( "twelvePm.toString(): " + twelvePm );
twelveAm.toString():00:23
12Py.toString():12:23
同样,我建议你尽可能使用24小时制。使生活更轻松,默认情况下使用LocalTime
类,并避免12小时时间模糊的错误和混淆。
您可以看到所有example code running live at IdeOne.com。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。