Java 8 LocalDate:确定每月的哪个星期一(第 1、第 2、第 3 等)
Posted
技术标签:
【中文标题】Java 8 LocalDate:确定每月的哪个星期一(第 1、第 2、第 3 等)【英文标题】:Java 8 LocalDate: Determine What Monday of the Month its (1st, 2nd, 3rd, etc) 【发布时间】:2018-06-17 17:29:10 【问题描述】:我试图弄清楚如何确定某个特定的星期一是给定月份的第一个、第二个、第三个或第四个星期一。我已经弄清楚如何使用 LocalDate 类来获取下周一和每月的一周。
LocalDate now = LocalDate.of(2018, 2, 1);
LocalDate nextMonday = now.with(next(DayOfWeek.MONDAY));
WeekFields weekFields = WeekFields.of(Locale.getDefault());
int week = nextMonday.get(weekFields.weekOfMonth());
在上面的示例中,代码获取下一个星期一和它所在的星期。星期是二月的第二个星期,但那个星期一不是第二个星期一,而是第一个星期一。对此的任何帮助将不胜感激。
【问题讨论】:
java2s.com/Tutorials/Java/java.time/LocalDate/index.htm 前 7 天的第一个星期一,接下来的 7 天的第二个星期一,依此类推。所以从月份中减去 1,除以 7,再加 1。 @AndyTurner 我并不热衷于将给定日期除以数字,你能举个例子吗? 有趣的问题:java.time
有类似Calendar.DAY_OF_WEEK_IN_MONTH
的东西吗?它用于设置月份中的星期几,例如将星期一更改为该月的第三个星期一:TemporalAdjusters.dayOfWeekInMonth
。但是为了得到?
【参考方案1】:
您不应该为此使用自己的算术。使用内置功能:
int week = nextMonday.get(ChronoField.ALIGNED_WEEK_OF_MONTH);
根据您的代码中的日期,这会产生:
1
这意味着您获得的星期一(2 月 5 日)是该月的第一个星期一。此外,您不需要任何 WeekFields
,因为无论哪一天是一周的第一天,或者一年中的周数如何编号,每个月的第一个星期一都是该月的第一个星期一。
日期算术通常很复杂且容易出错。这也意味着即使您最终计算正确,读者也很难说服自己/他自己您的代码是正确的。因此,最好使用我们相信要进行测试的内置功能,它使用解释性名称而不是像 1 和 7 这样的数字。
您可能会对要使用的字段名为ALIGNED_WEEK_OF_MONTH
感到惊讶。将对齐的周视为从每月 1 日开始的一周,无论是在一周中的哪一天,以及接下来的几周。 2018 年 2 月,第一个对齐周从 2 月 1 日星期四到 2 月 7 日星期三。接下来的对齐周从 2 月 8 日、2 月 15 日和 2 月 22 日星期四开始。显然,该月的第一个星期一在对齐的第 1 周,第 2 周的第 2 个星期一等。因此可以使用 ALIGNED_WEEK_OF_MONTH
。
【讨论】:
【参考方案2】:编辑:您应该选择 Ole V. V 的答案 (ChronoField.ALIGNED_WEEK_OF_MONTH
) 而不是这个答案。
你可以算出月份中的哪一天,除以 7 再加上 1:
LocalDate nextMonday = now.with(next(DayOfWeek.MONDAY));
int weekNo = ((nextMonday.getDayOfMonth()-1) / 7) +1;
例如这段代码:
LocalDate now = LocalDate.of(2018, 2, 1);
for(int i = 0; i < 10; i++)
now = now.with(next(DayOfWeek.MONDAY));
int weekNo = ((now.getDayOfMonth()-1) / 7) +1;
System.out.println("Date : " + now + " == " + weekNo);
打印出以下内容,我相信这是你想要的……
Date : 2018-02-05 == 1
Date : 2018-02-12 == 2
Date : 2018-02-19 == 3
Date : 2018-02-26 == 4
Date : 2018-03-05 == 1
Date : 2018-03-12 == 2
Date : 2018-03-19 == 3
Date : 2018-03-26 == 4
Date : 2018-04-02 == 1
Date : 2018-04-09 == 2
【讨论】:
除以7前要减1,否则会说7号和1号不在同一周。 @AndyTurner 很好,已修复。 我相信@AndyTurner 的观点很好地说明了使用你自己的算法来完成这样的任务的危险。我建议您改用内置功能。 【参考方案3】:您可以尝试从日期中反复减去一周,直到月份发生变化。那么您执行该操作的次数将是原始日期的“该月一周中的第 X 天”。
编辑:一些代码。
LocalDate now = LocalDate.of(2018, 2, 1);
int i = 0;
Month originalMonth = now.getMonth();
while (now.getMonth() == originalMonth) // its an enum, you can do this
now = now.plusWeeks(-1);
i++;
System.out.println(i); // prints 1
【讨论】:
【参考方案4】:String[] arr = "2018-01-01", "2018-01-07", "2018-01-30", "2018-01-22",
"2018-01-25" ;
for (String str : arr)
LocalDate ld = LocalDate.parse(str);
ld = ld.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY));
int res = (ld.getDayOfMonth()/7) +
(Integer.min(1, ld.getDayOfMonth() % 7));
System.out.printf("%s => %d\n", str, res);
【讨论】:
以上是关于Java 8 LocalDate:确定每月的哪个星期一(第 1、第 2、第 3 等)的主要内容,如果未能解决你的问题,请参考以下文章
在 mongoDB 中存储 java 8 LocalDate
Java 8 LocalDate 到 JavaScript 日期
Java 8 Time Api 使用(LocalDate,LocalTime和LocalDateTime等)
Java 8 Time Api 使用(LocalDate,LocalTime和LocalDateTime等)