为什么 Calendar 和 SimpleDateFormat 显示错误的日期?
Why Calendar and SimpleDateFormat are showing a bad date?
我尝试从字符串中解析日期,但是当我打印它时,它显示了错误的日期。我的代码:
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 年?
首先,您设置了错误的日期,因为月份范围是 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
}
避免遗留日期时间 类 现在被 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 ) ;
我尝试从字符串中解析日期,但是当我打印它时,它显示了错误的日期。我的代码:
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 年?
首先,您设置了错误的日期,因为月份范围是 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
}
避免遗留日期时间 类 现在被 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 ) ;