Java gets the start and end dates of the week for a month

given a certain month of a year (yyyy-MM), get the weekly start and end dates of that month (yyyy-MM-dd, Monday is the first day and Sunday is the last day).
for example, given 2018-08, the first week of the month is from 2018-08-01 to 2018-08-05, the second week is from 2018-08-06 to 2018-08-12, and so on, the last week is 2018-08-27 to 2018-08-31,
such as 2018-07, The first week is from 2018-07-01 to 2018-07-01, and the last week is from 2018-07-30 to 2018-07-31
how to get it?

May.22,2021

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

  1. yyyy-MM convert to List < date >
  2. List < date > classifies by week to get a similar result map Map < Integer, List < date > (where key is the week)
  3. 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
  4. .

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

  1. YearMonth convert to List < LocalDate >
  2. List < LocalDate > classifies by week to get a result similar to map Map < Integer, List < LocalDate > > (in which key is the week)
  3. 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
  4. .

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

  1. YearMonth convert to List < LocalDate >
  2. 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

.

clipboard.png

ChronoField.ALIGNED_WEEK_OF_MONTH785WeekFieldsSUNDAY_START

clipboard.png



Collectors.groupingByCollectors.collectingAndThen

map

clipboard.png


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,

Menu