Java日历问题设置为12pm

时间:2013-01-11 21:04:34

标签: java calendar

我正在创建一个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上。

3 个答案:

答案 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)

TL;博士

上午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 );

Try it live

避免遗留日期时间类

你正在使用现在遗留下来的麻烦的旧日期时间类,在Java 8及更高版本的java.time中取代,在adaptationjava.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.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore