【问题标题】:Why Calendar and SimpleDateFormat are showing a bad date?为什么 Calendar 和 SimpleDateFormat 显示错误的日期?
【发布时间】:2018-04-20 10:20:17
【问题描述】:

我尝试从字符串中解析日期,但是当我打印它时,它显示了错误的日期。我的代码:

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.text.SimpleDateFormat;

public class Main {
    public static void main(String args[]) {
        String some_date = "2017-12-31";
        Calendar cal_aux = GregorianCalendar.getInstance();
        System.out.println("set calendar: " + Integer.parseInt(some_date.substring(0, 4))
                + Integer.parseInt(some_date.substring(5, 7))
                + Integer.parseInt(some_date.substring(8, 10)));
        cal_aux.set(Integer.parseInt(some_date.substring(0, 4)),
                Integer.parseInt(some_date.substring(5, 7)),
                Integer.parseInt(some_date.substring(8, 10)));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("sdf calendar: " + sdf.format(cal_aux.getTime()));
    }
}

控制台输出:

set calendar: 20171231
sdf calendar: 2018-01-31 12:51:02

为什么当我使用简单的日期格式时,我得到的是 2018 而不是 2017?

【问题讨论】:

  • 请将您的问题编辑成英文,并提供minimal reproducible example。 (或者,当然可以找到最合适的非英语 Stack Overflow 站点 - es.stackoverflow.com?)
  • 您忘记从月份值中减去 1。您输入的月份是 12,表示 12 月,但 Calendar.set()javadoc 表示 "month - 用于设置 MONTH 日历字段的值。月份值为 从 0 开始。例如,0 代表 1 月。” 这是Calendar 的常见陷阱,而您是最新的受害者。
  • 我投票结束这个问题,因为它不是用英文写的。
  • 您正在使用现在遗留的麻烦类,被 java.time 类所取代。

标签: java datetime simpledateformat java.util.calendar


【解决方案1】:

避免旧的日期时间类现在被 java.time 类取代。有问题的遗留类有许多设计错误。一个这样的错误是将月份计算为 0-11 而不是 1-12。这种疯狂的计数正在破坏您的代码。

不要将日期时间值作为字符串进行操作。使用对象。

对于该仅日期值,请使用 LocalDate

LocalDate ld = LocalDate.parse( "2017-12-31" )  ;  // Or LocalDate.now() for today's date.

使用DateTimeFormatter 生成字符串。

String output = ld.format( DateTimeFormatter.BASIC_ISO_DATE ) ;

20171231

如果需要,指定时间。

LocalTime lt = LocalTime.of( 6 , 15 ) ;
LocalDateTime ltd = LocalDateTime.of( ld , lt ) ;

如果您想要一个实际的时刻,即时间线上的特定点,请应用时区。

ZoneId z = ZoneId.of( "Africa/Casablanca" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;

【讨论】:

  • Calendar 类出错的另一件事是,即使它的月份是 0 到 11,它仍然接受 12 作为月份值,并且仅将其表示为次年的一月.对大多数人来说非常令人惊讶,而且通常是负面的。
【解决方案2】:

首先,您设置了错误的日期,因为月份范围是 0-11。当您在月份字段中设置 12 时,是 2018 年 1 月而不是 2017 年 12 月。

其次,您可以简化程序,将输入字符串解析为格式化日期,并将此日期解析为输出格式化字符串。这是一个例子:

String input = "20171231";
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyyMMdd");
SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

try {
    System.out.println(outputFormat.format(inputFormat.parse(input)));
} catch (ParseException e) {
    // Log error
}

【讨论】:

    猜你喜欢
    • 2020-12-09
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 2019-01-19
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多