Calendar.getTime IllegalArgumentException [duplicate]

问题描述 投票:0回答:2
import java.util.Calendar;

public class WeekYear {
    static String input = "202001";
    //static String format = "YYYYMM";

    public static void main(String[] args) throws ParseException {
        Calendar lCal = Calendar.getInstance();
        System.out.println(lCal.isLenient());
        lCal.setLenient(false);
        lCal.set(Calendar.YEAR, new Integer(input.substring(0, 4)).intValue());
        lCal.set(Calendar.WEEK_OF_YEAR, new Integer(input.substring(4, 6)).intValue());
        //lCal.setMinimalDaysInFirstWeek(5);
        System.out.println(lCal.isLenient());
        System.out.println(lCal.getTime());

        //lCal.set(Calendar.YEAR, new Integer(input.substring(0, 4)).intValue());
        //lCal.set(Calendar.WEEK_OF_YEAR, new Integer(input.substring(4, 6)).intValue());
        //System.out.println(lCal.getTime());
    }
}

此代码在2020年11月22日执行时,我从Calendar.getTime()得到一个IllegalArgumentException。但是在2020年11月27日执行时,效果很好。

文档说:

setLenient(boolean leniency)类中的Calendar方法用于指定日期和时间的解释是否宽松。参数:该方法采用leniency类型的一个参数boolean,它引用日历的模式。

任何解释吗?

java illegalargumentexception week-number java.util.calendar java-calendar
2个回答
1
投票

tl; dr

从不使用Calendar(现在已成为旧版),已被java.time类(例如ZonedDateTime)取代。

使用专门构建的类,来自YearWeek项目的YearWeek,跟踪标准ThreeTen-Extra

自定义格式器

定义ISO 8601 weeks对象以匹配您的非标准输入字符串。

DateTimeFormatter

2020-W01

标准格式器

或操纵您的输入字符串以遵守org.threeten.extra.YearWeek .parse( "202001" , new DateTimeFormatterBuilder() .parseCaseInsensitive() .appendValue( IsoFields.WEEK_BASED_YEAR, 4, 10, SignStyle.EXCEEDS_PAD) .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2) .toFormatter() ) .toString() ,在基于周的年份和星期之间的中间插入ISO 8601 standard format。在解析/生成字符串时,默认情况下,java.time类和ThreeTen-Extra类均使用ISO 8601格式。

-W

yearWeek.toString():2020-W01

避免使用旧的日期时间类

[不要浪费时间尝试理解String input = "202001"; String inputModified = input.substring( 0 , 4 ) + "-W" + input.substring( 4 ); YearWeek yearWeek = YearWeek.parse( inputModified ) ; 。几年前,这个可怕的类被JSR 310中定义的现代java.time类所取代。

星期的定义

您必须指定一周的定义。您是说第1周包含一年的第一天吗?还是第1周包含一周中的某天?还是#1周是第一个完全包含新年日期的日历周?还是特定于行业的周定义?其他定义?

Calendar令人困惑的事情之一是它对一周的定义偏移了Calendar。这是避免该传统类的许多原因之一。

基于周的年份

根据您对周的定义,一周的年份可能不是该周某些日期的日历年。以周为基础的年份可能与日历年份重叠。

标准周和周基年

例如,Locale将一周定义为:

  • [从星期一开始,然后
  • 第1周包含日历年的第一个星期四。

因此,每个每周的年度有52或53个整周。当然,这意味着上一个日历年和/或下一个日历年的某些日期可能会出现在我们基于周的年份的第一周/最后一周。

standard ISO 8601 week

一个问题是,您试图用一个代表时刻的类来代表一年中的一周,该时刻代表着时区中的日期和时间。

相反,请使用专门构建的类。您可以在org.threeten.extra.YearWeekThreeTen-Extra中找到一个。该库扩展了Java 8及更高版本中内置的java.time类的功能。

[使用该类,我认为我们可以定义一个YearWeek以使用格式模式YearWeek来解析您的输入,其中DateTimeFormatter表示以周为基础的年份的4位数年,而YYYYww表示两位数的星期数。像这样:

YYYY

但是出于逃避我的原因,使用该格式化程序会抛出ww。>

线程“主”中的异常java.time.format.DateTimeParseException:无法解析文本'202001':无法从TemporalAccessor获取YearWeek:{WeekOfWeekBasedYear [WeekFields [SUNDAY,1]] = 1,WeekBasedYear [WeekFields [SUNDAY ,1]] = 2020},类型为java.time.format.Parsed的ISO

原因:java.time.DateTimeException:无法从TemporalAccessor获取YearWeek:{WeekOfWeekBasedYear [WeekFields [SUNDAY,1]] = 1,WeekBasedYear [WeekFields [SUNDAY,1]] = 2020},类型为java.time的ISO .format.Parsed

原因:java.time.temporal.UnsupportedTemporalTypeException:不支持的字段:WeekBasedYear

或者,我们可以使用// FAIL String input = "202001" ; DateTimeFormatter f = DateTimeFormatter.ofPattern( "YYYYww" ) ; YearWeek yearWeek = YearWeek.parse( input , f ) ; 从零件中构建DateTimeParseException。通过将Java 13的DateTimeParseException读为DateTimeFormatterBuilder,我可以将这个似乎有用的格式化程序拼凑在一起。

DateTimeFormatter

使用:

the OpenJDK source code

ISO 8601

教育您的数据发布者有关DateTimeFormatter.ISO_WEEK_DATE标准的定义,该标准定义了用文本表示日期时间值的格式。

要生成表示我们DateTimeFormatter.ISO_WEEK_DATE值的标准格式的字符串,请调用DateTimeFormatter f = new DateTimeFormatterBuilder() .parseCaseInsensitive() .appendValue( IsoFields.WEEK_BASED_YEAR, 4, 10, SignStyle.EXCEEDS_PAD) .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2) .toFormatter() ;

String input = "202001" ; 
YearWeek yearWeek = YearWeek.parse( input , f ) ;

2020-W01

并解析标准字符串。

ISO 8601

1
投票

Basil Bourque已经提供了一个很好的答案。这是一种不需要外部依赖的程序(前提是您使用的是Java 8或更高版本)。

© www.soinside.com 2019 - 2024. All rights reserved.