給定某年某月(yyyy-MM), 獲取該月的每周的開始日期和結(jié)束日期(yyyy-MM-dd,每周周一為第一天,周日為最后一天),
比如給定2018-08,該月第一周為2018-08-01至2018-08-05,第二周為2018-08-06至2018-08-12,以此類推,最后一周為2018-08-27至2018-08-31,
再如2018-07,第一周為2018-07-01至2018-07-01,最后一周為2018-07-30至2018-07-31.
該如何求?
Java8 LocalDate 了解一下
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());
// 該月的第一個(gè)周一
LocalDate start = date.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
List<String> list = new ArrayList<>();
// 處理每個(gè)月的1號(hào)不是周一的情況
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());
}題主,以下是我的思考思路,僅供參考:
讀完需求,感覺輸入輸出大體是這個(gè)樣子,
輸入:yyyy-MM年月日期一個(gè)
輸出:返回該年月所在月的所有周信息(每周的起始日期和結(jié)束日期)
既然是通過某一個(gè)月找到該月每周的起始日期、結(jié)束日期,那換句話說,一個(gè)月里有很多日期,這么日期它可以按照周來分類,第一周的日期為一類,第二周的日期為一類,以此類推,然后每一類中按照日期升序排序,我取第一個(gè)日期和最后一個(gè)日期最終就可以達(dá)到題主要求了,至此除了輸入輸出外,中間過程應(yīng)該是這個(gè)樣子
輸入:yyyy-MM年月日期一個(gè)
yyyy-MM轉(zhuǎn)化為List<日期>
List<日期>按照周進(jìn)行分類得到類似一個(gè)map的結(jié)果Map<Integer, List<日期>>(其中key就是第幾周)Map<Integer, List<日期>>中每一個(gè)List<日期>取第一個(gè)值得到該周的第一天,取最后一個(gè)值得到該周的最后一天輸出:返回該年月所在月的所有周信息(每周的起始日期和結(jié)束日期)
有了以上一個(gè)步驟,我們?cè)賮硪灰唤鉀Q步驟需要用到的代碼,當(dāng)然我這里沒有選擇用 java calender 類,emmm,我覺得它們實(shí)在太臃腫了,也容易犯錯(cuò),API也不太好用,就以Java8的新時(shí)間API來替代了
在Java8的新時(shí)間API中,以前表示一個(gè)時(shí)間的龐大齊全的Date類被拆分了成了很多類(以前一個(gè)Date對(duì)象既表現(xiàn)了日期,也表現(xiàn)了時(shí)間,也表現(xiàn)了時(shí)區(qū),大而全但不好用),這里我們要用到的是僅表示日期的YearMonth(yyyy-MM)和LocalDate(yyyy-MM-dd),YearMonth就表達(dá)一個(gè)年月,LocalDate就表達(dá)一個(gè)年月日
所以上訴需求立馬轉(zhuǎn)換為
輸入:YearMonth年月日期一個(gè)
YearMonth轉(zhuǎn)化為List<LocalDate>
List<LocalDate>按照周進(jìn)行分類得到類似一個(gè)map的結(jié)果Map<Integer, List<LocalDate>>(其中key就是第幾周可以)Map<Integer, List<LocalDate>>中每一個(gè)List<LocalDate>取第一個(gè)值得到該周的第一天,取最后一個(gè)值得到該周的最后一天輸出:返回該年月所在月的所有周信息(每周的起始日期和結(jié)束日期)
由于最終我們是在List<LocalDate>中取第一個(gè)日期和最后一個(gè)日期作為最終返回結(jié)果,因此套用那句我不知道在哪里看到的話:引用新的編程元素,可以增加代碼的可讀性,所以我們加一個(gè)新的類型WeekData來表示這么一個(gè)返回結(jié)果
static class WeekData{
// 一周的開始時(shí)間
private LocalDate start;
// 一周的結(jié)束時(shí)間
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 "開始時(shí)間:" + this.start + ",結(jié)束時(shí)間:" + this.end;
}
}
所以上訴需求立馬轉(zhuǎn)換為
輸入:YearMonth年月日期一個(gè)
YearMonth轉(zhuǎn)化為List<LocalDate>
List<LocalDate>按照周進(jìn)行分類得到類似一個(gè)map的結(jié)果Map<Integer, WeekData>(其中key就是第幾周可以)輸出:返回該年月所在月的所有周信息(每周的起始日期和結(jié)束日期)
現(xiàn)在就可以來解決每個(gè)步驟代碼了,這樣一個(gè)轉(zhuǎn)換的方法,初始狀態(tài)肯定是這樣YearMonth作為傳參,返回一個(gè)Map<Integer, WeekData>
private static Map<Integer, WeekData> weeks(YearMonth yearMonth){
// TODO
}
第一個(gè)步驟,YearMonth轉(zhuǎn)化為List<LocalDate>,表示的是這個(gè)月的所有日期,這種List<LocalDate>的,我第一想法就是用Java8的stream,首先根據(jù)yearMonth獲得這個(gè)月的開始日期和結(jié)束日期,用LocalDate的with方法即可,with就是調(diào)整的意思,想啥調(diào)整就咋調(diào)整非常靈活,隨便取一個(gè)日期(我這里取的是但當(dāng)前日期)
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());
}
完成。。。是很簡(jiǎn)單吧,還有封裝好的TemporalAdjusters.firstDayOfMonth()和TemporalAdjusters.lastDayOfMonth()
接下來我們來構(gòu)造stream,用Stream.iterate(start, localDate -> localDate.plusDays(1l))構(gòu)造一個(gè)無(wú)限流,它代表,以start作為起始值,按照第二個(gè)參數(shù)localDate -> localDate.plusDays(1l)也就是加一天的方式構(gòu)造一個(gè)無(wú)限流,當(dāng)然我要的不是無(wú)限,而是要到這個(gè)月末,所以limit(ChronoUnit.DAYS.between(start, end) + 1),這樣就把這個(gè)無(wú)限流截?cái)嗔?/p>
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());
}
這樣第一步就完成了,第二步,按周分類,這里有一個(gè)知識(shí)點(diǎn),給一個(gè)LocalDate對(duì)象,怎么判斷它是該月的第幾周,這里肯定要用LocalDate的get方法,因?yàn)檫@個(gè)方法就是表示從當(dāng)前日期中獲取某個(gè)屬性值,參數(shù)是接口TemporalField,你需要傳入一個(gè)實(shí)現(xiàn)類即可,這個(gè)實(shí)現(xiàn)類就是定義了這個(gè)屬性,當(dāng)然JDK默認(rèn)有一個(gè)實(shí)現(xiàn)類枚舉ChronoField,里面有很多好用的實(shí)現(xiàn)類可以用,所以很容易就會(huì)選到一個(gè)枚舉ChronoField.ALIGNED_WEEK_OF_MONTH,看起來好像是對(duì)的,ALIGNED不認(rèn)識(shí),WEEK_OF_MONTH感覺意思很明白,貌似能用,其實(shí)不然,這個(gè)實(shí)現(xiàn)類定義的一周跟我們想象中的不一樣,它的一周是按照完整7天來算的,拿8月6號(hào)來看,我們感覺是第二周,但是實(shí)際結(jié)果是第一周,因?yàn)橐獫M打滿算的7天才算一周,8月6號(hào)還是算第一周的第六天而已
所以得換個(gè)方法,ChronoField.ALIGNED_WEEK_OF_MONTH是按照周的一共7天這個(gè)維度來定義周,但是跟我們想要的周定義不太一樣,我們定義的周,例如8月,前面的5天就應(yīng)該是第一周了,也就是說,我們想象的周,不是說幾天是一周,應(yīng)該是周一是一周的開始,周日是一周的結(jié)束,就算只有一個(gè)周日,那也是一周,所以我們就看到另一個(gè)類WeekFields其中的靜態(tài)變量SUNDAY_START
從注釋來看是我們要的,不過是以星期天為一周開始的(這是國(guó)外的默認(rèn)了,國(guó)內(nèi)還是以周一為第一周開始的),所以我們直接用它的方式來構(gòu)造一個(gè)就可以啦
localDate.get(WeekFields.of(DayOfWeek.MONDAY, 1).weekOfMonth()
最后完整的就是
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());
Map<Integer, WeekData> map = Stream.iterate(start, localDate -> localDate.plusDays(1l))
.limit(ChronoUnit.DAYS.between(start, end)+1)
.collect(Collectors.groupingBy(localDate -> localDate.get(WeekFields.of(DayOfWeek.MONDAY, 1).weekOfMonth()),
Collectors.collectingAndThen(Collectors.toList(), WeekData::new)));
return map;
}
最后用了哈Collectors.groupingBy和Collectors.collectingAndThen配合了下,總之還算是比較簡(jiǎn)潔的寫法,希望能幫到你
最后簡(jiǎn)單打印哈獲得map,看看結(jié)果
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;curDay++){
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;
}
dayOfWeek++;
}
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();i++){
String arr[] = result.get(i);
System.out.println("第"+weekPrefixArray[i]+"周為"+arr[0]+ "至" + arr[1]);
}
}
}
大概思路吧,代碼寫的不嚴(yán)謹(jǐn),看看吧。
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國(guó)IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國(guó)家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國(guó)一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國(guó)成功上市,融資1
北大課工場(chǎng)是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國(guó)家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國(guó)制造2025”,實(shí)現(xiàn)中華民族偉大復(fù)興的升級(jí)產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國(guó)職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫(kù),具有快速界面開發(fā)的能力,對(duì)瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁(yè)制作和網(wǎng)頁(yè)游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國(guó)Software AG 技術(shù)顧問,美國(guó)Dachieve 系統(tǒng)架構(gòu)師,美國(guó)AngelEngineers Inc. 系統(tǒng)架構(gòu)師。