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

Java 为什么(MonthName.format(c.get(Calendar.MONTH)))返回错误的月份?,java,calendar,Java,Calendar,虽然系统时间显示为March,但我还是尝试了Java中的Time类和以下输出: Calendar c = Calendar.getInstance(); SimpleDateFormat MonthName = new SimpleDateFormat("MMMM"); System.out.println(MonthName.format(c.get(Calendar.MONTH))); 但使用这个方法可以返回三月: System.out.println(MonthName.format(c

虽然系统时间显示为March,但我还是尝试了Java中的Time类和以下输出:

Calendar c = Calendar.getInstance();
SimpleDateFormat MonthName = new SimpleDateFormat("MMMM");
System.out.println(MonthName.format(c.get(Calendar.MONTH)));
但使用这个方法可以返回三月:

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

我知道JAVA中的月份计数是从0开始的,而不是从1开始的,所以显示二月是合适的,但显示三月是合适的

SimpleDataFormat需要的是日期,而不是月号

Calendar c = Calendar.getInstance();
Date d = c.getTime();
SimpleDateFormat MonthName = new SimpleDateFormat("MMMM");    
System.out.println(MonthName.format(d));
因为
c.get(Calendar.MONTH)
返回一个数字,调用
format(number)
与调用
format(new Date(number))
(检查)是一样的

在本例中,
c.get(Calendar.MONTH)
返回
2
,因为正如您所说,此API使用基于0的月份,所以三月是2

当您调用
格式(2)
时,它相当于调用
格式(新日期(2))
,这意味着对应于“2毫秒之后”的日期,即
1970-01-01T00:00:00.002
(基本上,1970年1月1日午夜后2毫秒在UTC

然后,这个日期(1970年1月1日UTC)将由使用JVM默认时区的
SimpleDataFormat
格式化。因此,当该日期(对应UTC中的1月1日)转换为JVM默认时区时,将显示“12月”。只需打印
新日期(2)
的值,然后查看结果(扰流板:日期将在1969年12月31日)


您的第二次尝试之所以有效,是因为
c.getTime()
返回一个
java.util.Date
,在本例中,它将对应于三月;博士 java.time 答案是正确的

现代方法使用java.time类取代了麻烦的旧遗留日期时间类(
date
Calendar
SimpleDateFormat

将表示时间线上某一时刻的
日历
替换为特定地区(时区)的人使用的挂钟时间,分辨率为纳秒

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.
检索此
ZoneDateTime
对象日期所在月份的枚举对象

Month month = zdt.getMonth() ;
生成自动本地化的月份名称字符串。要本地化,请指定:

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

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

关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

该项目现已启动,建议迁移到类

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

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

从哪里获得java.time类

  • ,及以后
    • 内置的
    • 标准JavaAPI的一部分,带有捆绑实现
    • Java9添加了一些次要功能和修复
    • 大部分java.time功能都在中向后移植到Java6和Java7
    • 更高版本的Android捆绑包实现了java.time类

    • 对于早期的Android(
      SimpleDateFormat
      是一个日期格式化程序,而不是月数格式化程序。请尝试更改日期格式模式以包含日期和年份。
      Locale locale = Locale.US ;  // Or Locale.CANADA_FRENCH etc.
      String monthName = month.getDisplayName( FormatStyle.FULL , locale ) ;