在旧的java中,我可以这样做:
System.out.println(new SimpleDateFormat("yyyy w", Locale.UK).parse("2015 1"));
// shows Mon Dec 29 00:00:00 CET 2014
System.out.println(new SimpleDateFormat("yyyy w", Locale.US).parse("2015 1"));
// shows Mon Dec 28 00:00:00 CET 2014
我想在Java 8中使用java.time。
System.out.println( LocalDate.parse("2015 1", DateTimeFormatter.ofPattern("yyyy w", Locale.US)));
结果:
java.time.format.DateTimeParseException:无法解析文本'2015 1':无法从TemporalAccessor获取LocalDate:{WeekOfWeekBasedYear [WeekFields [SUNDAY,1]] = 1,Year = 2015},ISO类型为java .time.format.Parsed
如何在java.time中执行此操作?
此外,我不满意我必须通过Locale来确定一周的第一天:星期一和星期日。它不是乡村功能,而是日历功能。我想使用像java.time.temporal.WeekFields.ISO这样的东西来显示星期一从星期一开始的世界
我发现了类似的案例:https://stackoverflow.com/questions/3941700/how-to-get-dates-of-a-week-i-know-week-number
但不适用于Java 8中的java.time。此外,首先创建日期对象并稍后设置正确周的解决方案并不优雅。我想一次创建最终日期。
答案 0 :(得分:5)
直接回答和解决方案:
System.out.println(
LocalDate.parse("2015 1",
new DateTimeFormatterBuilder().appendPattern("YYYY w")
.parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
.toFormatter()));
// output: 2014-12-29
<强>说明:强>
a)您应该使用Y代替y,因为您对ISO-8601周日期感兴趣,而不是在年代。
b)仅通过给出(基于周的)年和周数不能形成日历日期。星期几很重要,以确定指定日历周内的日期。预定义的formatter for week-dates要求缺少星期几。所以你需要使用builder-pattern构建一个专门的解析器。然后有必要通过方法parseDefaulting()
告诉解析器星期几是哪一天。
WeekFields.ISO.dayOfWeek()
来应用ISO-8601标准。 注意:测试显示,ChronoField.DAY_OF_WEEK
与Locale.ROOT
一起使用似乎并不总能保证ISO周的行为,如我在第一个版本中所示(原因是对我来说尚不清楚 - 对源代码的密切观察似乎有必要启发不直观的行为。)
d)java-time-package做得很好 - 除了星期一被指定为数字1.我会更喜欢枚举。或者使用枚举及其方法getValue()
。
e)侧面通知:默认情况下SimpleDateFormat
行为宽松。 java-time-package更加严格,拒绝用空气来创造一个缺少的星期几 - 即使在宽松的模式下(在我看来这是一件好事)。软件不应该如此猜测,相反,程序员应该更多地考虑哪一天是正确的。再次:在美国和法国,关于正确的默认设置,应用程序要求可能会有所不同。
答案 1 :(得分:2)
accepted Answer by Meno Hochschild是正确的。这是另一条路线。
YearWeek
使用YearWeek
库中的ThreeTen-Extra课程。该库扩展了具有附加功能的java.time。此特定类代表ISO 8601 week date system中的一年周。
工厂方法YearWeek.of
采用一对整数参数,基于周的年份和周数。
YearWeek yw = YearWeek.of( 2015 , 1 );
理想情况下,您将对表示日期时间值的字符串使用标准ISO 8601格式。对于year-week that would be yyyy-Www
基于周的年份数字,连字符,W
和周数的两位数,根据需要填充零。
2015-W01
java.time类和ThreeTen-Extra类在解析和生成字符串时默认使用标准的ISO 8601格式。因此,如果你坚持标准,那么生活就会更容易
。YearWeek yw = YearWeek.parse( "2015-W01" );
String output = yw.toString(); // 2015-W01
您有一个非标准的数字格式。因此,让我们将您的字符串解析为两个部分,每个部分一个数字,以解释为int
整数。
String string = "2015 1";
String[] parts = string.split(" "); // SPACE character.
String part1 = parts[0]; // 2015
String part2 = parts[1]; // 1
Integer
类将此类字符串转换为int
原始值。
int weekBasedYearNumber = Integer.parseInt( part1 ) ;
int weekNumber = Integer.parseInt( part2 ) ;
现在调用该工厂方法。
YearWeek yw = YearWeek.of( weekBasedYearNumber , weekNumber );
LocalDate
至于一周的第一天,我们一直在讨论标准的ISO 8601周定义。在该定义中,星期一总是第一天,从星期一到星期日运行一周。第1周包含日历年的第一个星期四。在2015-W01的情况下,星期四将是2015年1月1日。
所以,不需要Locale
。
我不太确定你的目标,但它似乎在提取你一周内的特定日期。使用YearWeek
类和DayOfWeek
枚举非常简单。
LocalDate monday = yw.atDay( DayOfWeek.MONDAY ); // 2014-12-29 start-of-week.
LocalDate friday = yw.atDay( DayOfWeek.FRIDAY ); // 2015-01-02
LocalDate sunday = yw.atDay( DayOfWeek.SUNDAY ); // 2015-01-04 end-of-week.
答案 2 :(得分:0)
这也可以通过使用“ChronoField.Day_Of_Week”为星期几设置默认分析值并将值设置为“1”来实现,如下所示:
size()