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
,它引用日历的模式。
任何解释吗?
从不使用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
将一周定义为:
因此,每个每周的年度有52或53个整周。当然,这意味着上一个日历年和/或下一个日历年的某些日期可能会出现在我们基于周的年份的第一周/最后一周。
一个问题是,您试图用一个代表时刻的类来代表一年中的一周,该时刻代表着时区中的日期和时间。
相反,请使用专门构建的类。您可以在org.threeten.extra.YearWeek
库ThreeTen-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 codeISO 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
Basil Bourque已经提供了一个很好的答案。这是一种不需要外部依赖的程序(前提是您使用的是Java 8或更高版本)。