我试图将一些代码从joda时间移植到java时间。
parser.withDefaultYear((new DateTime(DateTimeZone.UTC)).getYear()).parseDateTime(text);
如果您对传入日期格式没有任何控制,因为它是用户提供的,这就使得何时调用ParseDefaulting
变得非常困难。
是否有任何解决办法,在这里我可以指定一些东西,比如通用回退日期,如果没有指定,格式化程序将使用其值,或者当格式化程序中指定回退值时,我如何配置根本不使用的回退值?
下面是最小的、完整的和可验证的示例。
public static DateTimeFormatter ofPattern(String pattern) {
return new DateTimeFormatterBuilder()
.appendPattern(pattern)
.parseDefaulting(ChronoField.YEAR, 1970)
.toFormatter(Locale.ROOT);
}
public void testPatterns() {
// works
assertThat(LocalDate.from(ofPattern("MM/dd").parse("12/06")).toString(), is("1970-12-06"));
assertThat(LocalDate.from(ofPattern("uuuu/MM/dd").parse("2018/12/06")).toString(), is("2018-12-06"));
// fails with exception, as it uses year of era
assertThat(LocalDate.from(ofPattern("yyyy/MM/dd").parse("2018/12/06")).toString(), is("2018-12-06"));
}
无法分析文本“2018/12/06”:发现冲突:1970年与2018年不同
Exception in thread "main" java.time.format.DateTimeParseException: Text '2018/12/06' could not be parsed: Conflict found: Year 1970 differs from Year 2018
at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1959)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1820)
at com.ajax.mypackage.MyTest.testPatterns(MyTest.java:33)
Caused by: java.time.DateTimeException: Conflict found: Year 1970 differs from Year 2018
at java.base/java.time.chrono.AbstractChronology.addFieldValue(AbstractChronology.java:676)
at java.base/java.time.chrono.IsoChronology.resolveYearOfEra(IsoChronology.java:620)
at java.base/java.time.chrono.IsoChronology.resolveYearOfEra(IsoChronology.java:126)
at java.base/java.time.chrono.AbstractChronology.resolveDate(AbstractChronology.java:463)
at java.base/java.time.chrono.IsoChronology.resolveDate(IsoChronology.java:585)
at java.base/java.time.chrono.IsoChronology.resolveDate(IsoChronology.java:126)
at java.base/java.time.format.Parsed.resolveDateFields(Parsed.java:360)
at java.base/java.time.format.Parsed.resolveFields(Parsed.java:266)
at java.base/java.time.format.Parsed.resolve(Parsed.java:253)
at java.base/java.time.format.DateTimeParseContext.toResolved(DateTimeParseContext.java:331)
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1994)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1816)
... 1 more
ParseDefaulting
将在未找到字段时设置该字段的值,即使对于不在模式中的字段也是如此,因此最终可能会出现year和year-of-era同时出现在解析结果中的情况。
对我来说,最简单的解决方案是注释中建议的:使用regex检查输入是否包含一年(或类似于一年的东西,如4位数),或者检查输入的长度,然后相应地创建格式化程序(并且不使用默认值)。例子:
if (input_without_year) {
LocalDate d = MonthDay
.parse("12/06", DateTimeFormatter.ofPattern("MM/dd"))
.atYear(1970);
} else {
// use formatter with year, without default values
}
但如果你想要一个通用的解决方案,恐怕就更复杂了。另一种方法是解析输入并检查其中是否有year字段。如果没有,那么我们将其更改为返回一年的默认值:
public static TemporalAccessor parse(String pattern, String input) {
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern, Locale.ROOT);
final TemporalAccessor parsed = fmt.parse(input);
// check year and year of era
boolean hasYear = parsed.isSupported(ChronoField.YEAR);
boolean hasYearEra = parsed.isSupported(ChronoField.YEAR_OF_ERA);
if (!hasYear && !hasYearEra) {
// parsed value doesn't have any year field
// return another TemporalAccessor with default value for year
// using year 1970 - change it to Year.now().getValue() for current year
return withYear(parsed, 1970); // see this method's code below
}
return parsed;
}
issupported
方法WithYear
方法如下:
public static TemporalAccessor withYear(TemporalAccessor t, long year) {
return new TemporalAccessor() {
@Override
public boolean isSupported(TemporalField field) {
// epoch day is used by LocalDate.from
if (field == ChronoField.YEAR_OF_ERA || field == ChronoField.EPOCH_DAY) {
return true;
} else {
return t.isSupported(field);
}
}
@Override
public long getLong(TemporalField field) {
if (field == ChronoField.YEAR_OF_ERA) {
return year;
// epoch day is used by LocalDate.from
} else if (field == ChronoField.EPOCH_DAY) {
// Assuming the input always have month and day
// If that's not the case, you can change the code to use default values as well,
// and use MonthDay.of(month, day)
return MonthDay.from(t).atYear((int) year).toEpochDay();
} else {
return t.getLong(field);
}
}
};
}
现在这个管用了:
System.out.println(LocalDate.from(parse("MM/dd", "12/06"))); // 1970-12-06
System.out.println(LocalDate.from(parse("uuuu/MM/dd", "2018/12/06"))); // 2018-12-06
System.out.println(LocalDate.from(parse("yyyy/MM/dd", "2018/12/06"))); // 2018-12-06
public static LocalDate parseLocalDate(String pattern, String input) {
DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern, Locale.ROOT);
// try to create a LocalDate first
// if not possible, try to create a MonthDay
TemporalAccessor parsed = fmt.parseBest(input, LocalDate::from, MonthDay::from);
LocalDate dt = null;
// check which type was created by the parser
if (parsed instanceof LocalDate) {
dt = (LocalDate) parsed;
} else if (parsed instanceof MonthDay) {
// using year 1970 - change it to Year.now().getValue() for current year
dt = ((MonthDay) parsed).atYear(1970);
} // else etc... - do as many checkings you need to handle all possible cases
return dt;
}
然后检查返回的类型并相应地执行操作。您可以扩展它以检查任意多个类型,还可以编写自己的TemporalQuery
来处理特定的情况。
有了这个,所有的案例也都起作用了:
System.out.println(parseLocalDate("MM/dd", "12/06")); // 1970-12-06
System.out.println(parseLocalDate("uuuu/MM/dd", "2018/12/06")); // 2018-12-06
System.out.println(parseLocalDate("yyyy/MM/dd", "2018/12/06")); // 2018-12-06
给予 什么是?它是实现定义的还是未定义的行为?C和C的答案不同吗?
在一个有2%左右填充的容器中,我有两个div框。左侧div框的宽度固定为200px,右侧边距固定为60px。我想要正确的div调整它的宽度,浏览器窗口变小/变大。我如何实现红色框的宽度(独立于浏览器的宽度)一直填充到容器的rigth填充开始,而蓝色div保持其200px? JSfiddle:http://jsfidle.net/3vhrst19/3/ HTML: CSS:
我想知道是否有任何可能的方法使用RecyclerView? 在此之前,我在ScrollView中使用了具有固定高度的RecyclerView,但这次我不知道项目的高度。 提示:在提出这个问题之前,我阅读了堆栈问题的所有问题和解决方案。 更新:一些解决方案显示了如何自行滚动RecyclerView,但我想显示它已扩展。
问题内容: 我现在两次遇到问题,生产者线程会产生N个工作项,将它们提交给an ,然后需要等待,直到所有N个项都已处理完毕。 注意事项 N事先未知 。如果是这样,我将简单地创建一个然后具有生产者线程,直到完成所有工作。 使用a 是不合适的,因为尽管我的生产者线程需要阻塞(即,通过调用),但 无法表示所有工作都已完成 ,从而导致生产者线程停止等待。 我当前喜欢的解决方案是使用整数计数器,并在提交工作项
本文向大家介绍javascript中活灵活现的Array对象详解,包括了javascript中活灵活现的Array对象详解的使用技巧和注意事项,需要的朋友参考一下 前言 JavaScript中的Array对象,就是我们常说的数组对象,主要用于封装多个任意类型的数据,并对它们进行管理。 所有主流浏览器均支持Array对象。 大家都知道Array实例有这四个方法:push、pop、shift、unsh