为什么(MonthName.format(c.get(Calendar.MONTH)))返回错误的月份?

时间:2018-03-16 16:08:22

标签: java calendar

我正在尝试Java中的Time类,以及12月的输出,即使系统时间显示March:

Calendar c = Calendar.getInstance();
SimpleDateFormat MonthName = new SimpleDateFormat("MMMM");
System.out.println(MonthName.format(c.get(Calendar.MONTH)));

但是使用它会返回March:

System.out.println(MonthName.format(c.getTime()));

我知道JAVA中的月数从0开始而不是1,所以它显示2月是合适的但是3月?

3 个答案:

答案 0 :(得分:4)

由于c.get(Calendar.MONTH)会返回一个号码,而调用format(number)与调用format(new Date(number))相同(请检查here)。

在这种情况下,c.get(Calendar.MONTH)会返回2,因为 - 正如您所说 - 此API使用的是基于0的月份,因此3月份为2。

当您拨打format(2)时,它相当于拨打format(new Date(2)),这意味着与unix epoch"之后的" 2毫秒相对应的日期,这是1970-01-01T00:00:00.002(基本上是1970年1月1日午夜后的2毫秒在UTC )。

然后,此日期(1970年1月1日 UTC )将由SimpleDateFormat格式化,new Date(2)使用JVM默认时区。因此,当该日期(对应于UTC中的1月1日)转换为您的JVM默认时区时,为您提供" 12月"。只需打印c.getTime()的值,看看你得到了什么(剧透:它将是1969年12月31日的日期)。

您的第二次尝试有效,因为java.util.Date会返回AppSettingsTextBoxes,在这种情况下会与3月相对应。

答案 1 :(得分:0)

SimpleDateFormat需要一个日期,而不是一个月号

Calendar c = Calendar.getInstance();
Date d = c.getTime();
SimpleDateFormat MonthName = new SimpleDateFormat("MMMM");    
System.out.println(MonthName.format(d));

答案 2 :(得分:0)

TL;博士

LocalDate.now()                  // Better to specify time zone explicitly: LocalDate.now( ZoneId.of( "Pacific/Auckland" ) )
    .getMonth                    // Get `Month` enum object appropriate to that date in that zone.
    .getDisplayName(             // Generate a `String`, the localized name of the month.
        FormatStyle.FULL ,       // Control how long or how abbreviated the text.
        Locale.CANADA_FRENCH     // Specify the human language and cultural norms to be applied in localizing.
    )

java.time

Answer by posutes是正确的。

现代方法使用 java.time 类来取代麻烦的旧遗留日期时间类(DateCalendarSimpleDateFormat)。

ZonedDateTime取代Calendar,用时间线上的时刻代表特定区域(时区)的人使用的挂钟时间,分辨率为纳秒。

ZonedDateTime zdt = ZonedDateTime.now() ;   // Would be better to pass explicitly the desired/expected time zone rather than implicitly rely on the JVM’s current default.

检索此ZonedDateTime对象日期月份的Month枚举对象。

Month month = zdt.getMonth() ;

为月份名称生成一个字符串,自动进行本地化。要进行本地化,请指定:

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

询问本地化的月份名称。

Locale locale = Locale.US ;  // Or Locale.CANADA_FRENCH etc.
String monthName = month.getDisplayName( FormatStyle.FULL , locale ) ;

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

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

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

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

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