subject, the following is my thinking, for reference only:
after reading the requirements, I feel that the input and output looks like this.
input: yyyy-MM
year, month, date, a
output: returns all weekly information (the start and end dates of each week) of the month of the year
since the start and end dates of each week of the month are found through a month, in other words, there are many dates in a month, so the dates can be classified according to weeks, the dates of the first week are classified into one category, the dates of the second week are of the same category, and so on, and then in each category, sorted in ascending order of dates, I can finally meet the requirements of the subject by taking the first date and the last date. So far, in addition to input and output, the intermediate process should look like this
enter: yyyy-MM
year, month, date, one
-
yyyy-MM
convert to List < date >
-
List < date >
classifies by week to get a similar result map
Map < Integer, List < date >
(where key
is the week)
-
Map < Integer, List < date >
each List < date >
take the first day of the week worth going to, and the last one worth going to the last day of the week .
output: returns all weekly information (the start and end dates of the week) for the month of the year
with the above step, let's solve the code needed in the step one by one. Of course, I didn't choose to use the java calender
class here. Emmm, I think they are too bloated and easy to make mistakes. API
is not easy to use, so I replace
with
Java8
's new time
API
.
in Java8
's new time API
, the large and complete Date
classes that used to represent a time are split into many categories (the previous Date
object represents not only the date, but also the time zone, which is large but not easy to use). Here we are going to use YearMonth
(yyyy-MM) and LocalDate
(yyyy-MM-dd). LocalDate
just express one year, month, day
so the appeal requirement is immediately converted to
enter: YearMonth
year, month, date, one
-
YearMonth
convert to List < LocalDate >
-
List < LocalDate >
classifies by week to get a result similar to map
Map < Integer, List < LocalDate > >
(in which key
is the week)
-
Map < Integer, List < LocalDate >
each List < LocalDate >
take the first day of the week worth going to, and the last one worth going to the last day of the week .
output: returns all weekly information (the start and end dates of the week) for the month of the year
since we finally take the first and last dates in List < LocalDate >
as the final return result, we paraphrase the phrase I don't know where to see: referencing a new programming element can increase the readability of the code, so we add a new type WeekData
to represent such a return
.
static class WeekData{
//
private LocalDate start;
//
private LocalDate end;
public WeekData(List<LocalDate> localDates) {
this.start = localDates.get(0);
this.end = localDates.get(localDates.size()-1);
}
@Override
public String toString() {
return ":" + this.start + ":" + this.end;
}
}
so the appeal request is immediately converted to
input: YearMonth
year, month and date
-
YearMonth
convert to List < LocalDate >
-
List < LocalDate >
classifies by week to get a similar result map
Map < Integer, WeekData >
(in which key
is the week)
output: returns all weekly information (the start and end dates of the week) for the month of the year
now you can solve the code of each step. For such a conversion method, the initial state must be like this YearMonth
as a parameter, return a Map < Integer, WeekData >
.
private static Map<Integer, WeekData> weeks(YearMonth yearMonth){
// TODO
}
the first step is to convert YearMonth
into List < LocalDate >
, which represents all the dates of the month. My first idea is to use stream
of Java8
, first obtain the start date and end date of this month according to yearMonth
, and use the with
method of LocalDate
. Take a random date (what I take here is but the current date)
private static Map<Integer, WeekData> weeks(YearMonth yearMonth){
LocalDate start = LocalDate.now().with(yearMonth).with(TemporalAdjusters.firstDayOfMonth());
LocalDate end = LocalDate.now().with(yearMonth).with(TemporalAdjusters.lastDayOfMonth());
}
complete. It's very simple, and there are TemporalAdjusters.firstDayOfMonth ()
and TemporalAdjusters.lastDayOfMonth ()
encapsulated.
next let's construct stream
, using Stream.iterate (start, localDate-> localDate.plusDays (11))
to construct an infinite stream, which represents, taking start as the starting value, constructing an infinite stream according to the second parameter localDate-> localDate.plusDays (11)
, that is, adding one day, of course, I don't want infinity, but until the end of this month, so limit (ChronoUnit.DAYS.between (start, end) + 1)
, In this way, the infinite flow is cut off
private static Map<Integer, WeekData> weeks(YearMonth yearMonth){
LocalDate start = LocalDate.now().with(yearMonth).with(TemporalAdjusters.firstDayOfMonth());
LocalDate end = LocalDate.now().with(yearMonth).with(TemporalAdjusters.lastDayOfMonth());
List<LocalDate> localDates = Stream.iterate(start, localDate -> localDate.plusDays(1l))
.limit(ChronoUnit.DAYS.between(start, end) + 1)
.collect(Collectors.toList());
}
so the first step is completed. The second step is classified by week. Here is a knowledge point. Give a LocalDate
object, how to determine which week of the month it is. Here you must use the get
method of LocalDate
, because this method is to get an attribute value from the current date, and the parameter is interface TemporalField
. You need to pass in an implementation class, which defines this attribute. Of course, JDK
has an implementation class enumeration ChronoField
by default, and there are many useful implementation classes available, so it is easy to choose an enumeration ChronoField.ALIGNED_WEEK_OF_MONTH
, which seems to be correct. ALIGNED
does not know, WEEK_OF_MONTH
feels clear and seems to work, but it is not. The week defined by this implementation class is different from what we imagined. Its week is calculated according to the full seven days. Taking August 6 as the point of view, we feel that it is the second week, but the actual result is the first week, because it takes seven full days to count as a week, and August 6th is still the sixth day of the first week
.
ChronoField.ALIGNED_WEEK_OF_MONTH
785WeekFields
SUNDAY_START
Collectors.groupingBy
Collectors.collectingAndThen
map
Java8 LocalDate
learn about
public static void main(String[] args) {
// Java8 LocalDate
LocalDate date = LocalDate.parse("2018-08-01");
//
LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
//
LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
//
LocalDate start = date.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
List<String> list = new ArrayList<>();
// 1
if (!firstDay.equals(start)) {
StringBuilder strbur = new StringBuilder();
strbur.append(firstDay.toString())
.append("")
.append(start.plusDays(-1).toString());
list.add(strbur.toString());
}
while (start.isBefore(lastDay)) {
StringBuilder strbur = new StringBuilder();
strbur.append(start.toString());
LocalDate temp = start.plusDays(6);
if (temp.isBefore(lastDay)) {
strbur.append("")
.append(temp.toString());
} else {
strbur.append("")
.append(lastDay.toString());
}
list.add(strbur.toString());
start = start.plusWeeks(1);
}
System.out.println(list.toString());
}
Please refer to the use of the java calender class, which meets all your needs. When using it, pay attention to the time zone, winter time and daylight saving time
have you taken into account the weekly cross-month situation?
package com.blog.web.front;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class Test{
/**
*
* @param date
* @param format
* @return
*/
public static String formatDate(Date date,String format){
if(null == format || "".equals(format.trim())){
format = "yyyy-MM-dd";
}
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
return dateFormat.format(date);
}
/**
*
* @param dateStr
* @param format
* @return
*/
public static Date parseDate(String dateStr,String format){
if(null == format || "".equals(format.trim())){
format = "yyyy-MM-dd";
}
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
try {
return dateFormat.parse(dateStr);
} catch (ParseException e) {
return null;
}
}
public static List<String[]> getAllWeek(String dateStr){
Date date = parseDate(dateStr,"yyyy-MM");
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.DAY_OF_MONTH, 1);
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
dayOfWeek = dayOfWeek == 0 ? 7 : dayOfWeek;
int days = c.getActualMaximum(Calendar.DAY_OF_MONTH);
List<String[]> result = new ArrayList<String[]>();
String[] array = null;
for(int curDay = 1;curDay <= days;curDayPP){
c.set(Calendar.DAY_OF_MONTH, curDay);
if(1 == curDay || 1 == dayOfWeek){
array = new String[2];
array[0] = formatDate(c.getTime(),null);
}
if(dayOfWeek == 7 || curDay == days){
array[1] = formatDate(c.getTime(),null);
result.add(array);
dayOfWeek = 0;
}
dayOfWeekPP;
}
return result;
}
public static void main(String[] args) {
List<String[]> result = getAllWeek("2018-07");
String[] weekPrefixArray = new String[]{"","","","","","","",""};
for(int i = 0;i < result.size();iPP){
String arr[] = result.get(i);
System.out.println(""+weekPrefixArray[i]+""+arr[0]+ "" + arr[1]);
}
}
}
about the train of thought, the code is not rigorous, take a look.
LocalDate now = LocalDate.now().minusMonths(2);
LocalDate firstDayOfNextMonth = now.with(TemporalAdjusters.firstDayOfNextMonth());
LocalDate firstDayOfMonth = now.with(TemporalAdjusters.firstDayOfMonth());
List<Pair<LocalDate, LocalDate>> list =
Stream.iterate(new Pair<>(firstDayOfMonth, firstDayOfMonth.plusDays(7 - firstDayOfMonth.getDayOfWeek().getValue()))
, it -> new Pair<>(it.getRight().plusDays(1), it.getRight().plusDays(7)))
.limit(8)
.filter(it -> it.getLeft().isBefore(firstDayOfNextMonth))
.map(it -> it.getRight().isBefore(firstDayOfNextMonth) ? it : new Pair<>(it.getLeft(), firstDayOfNextMonth.minusDays(1)))
.collect(Collectors.toList());
I think you should need this, knowing that the first Sunday of every one is not necessarily the first Sunday.
other weeks should be fine.
/\*\*
\* \* @param year
\* @param month
\* @return Date \*/public static Date getFirstSundayOfMonth(int year, int month) {
Calendar cal \= Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month \- 1);
//
cal.set(Calendar.DATE, 1);
while (cal.get(Calendar.DAY\_OF\_WEEK) != Calendar.SUNDAY) {
cal.add(Calendar.DATE, 1);
}
return cal.getTime();
}
for example, the first Sunday of 2020-3 is on March 1st
2020-4, and the first Sunday of March is April 5
. According to the above, the last week of March (the last day is Saturday) is April 4
as follows
3 br > the first week
3, br > 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 22, 3, 3, 3, 22, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,