package astro import ( "b612.me/astro/calendar" "fmt" "time" ) type Holiday struct { //假日开始时间 Start time.Time //假日结束时间 End time.Time //节日所在日期 Core time.Time //假日总天数 Total int //调休日期 Instead []time.Time //假日名称 Name string //法定假日天数 LegalDays int Comment string } func (h Holiday) BasicInfo() { xq := []string{"日", "一", "二", "三", "四", "五", "六"} _, m, _, str := calendar.RapidSolarToLunar(h.Core) gz := calendar.GanZhi(h.Core.Year()) if m > 10 && int(h.Core.Month()) < 3 { gz = calendar.GanZhi(h.Core.Year() - 1) } if h.Start.IsZero() { fmt.Println(h.Name + "无假期") return } fmt.Printf("节日: %s 法定假期: %d天 放假天数: %d天\n", h.Name, h.LegalDays, h.Total) fmt.Println("公历:", h.Core.Format("2006年01月02日"), "星期"+xq[h.Core.Weekday()]) fmt.Println("农历:", gz+str) if h.Comment != "" { fmt.Println(h.Comment) } } func (h Holiday) Detail() { if h.Start.IsZero() { return } xq := []string{"日", "一", "二", "三", "四", "五", "六"} if h.Start.Equal(h.End) || h.End.IsZero() { fmt.Printf("假期: %s(星期%s) 共%d天\n", h.Start.Format("2006年01月02日"), xq[h.Start.Weekday()], h.Total) } else { fmt.Printf("假期: %s(星期%s) - %s(星期%s) 共%d天\n", h.Start.Format("2006年01月02日"), xq[h.Start.Weekday()], h.End.Format("2006年01月02日"), xq[h.End.Weekday()], h.Total) } if len(h.Instead) > 0 { fmt.Print("调休: ") for idx, v := range h.Instead { fmt.Printf("%s(星期%s)", v.Format("01月02日"), xq[v.Weekday()]) if idx != len(h.Instead)-1 { fmt.Print("、") } } fmt.Println(" 上班") return } fmt.Println("不调休") } func target3Day1(date time.Time) Holiday { switch date.Weekday() { case 0: return Holiday{ Core: date, Start: date.Add(-24 * time.Hour), End: date.Add(24 * time.Hour), Total: 3, LegalDays: 1, } case 1: return Holiday{ Core: date, Start: date.Add(-48 * time.Hour), End: date, Total: 3, LegalDays: 1, } case 5, 6: return Holiday{ Core: date, Start: date, End: date.Add(48 * time.Hour), Total: 3, LegalDays: 1, } case 3: return Holiday{ Core: date, Start: date, End: date, Total: 1, LegalDays: 1, } case 2: return Holiday{ Core: date, Start: date.Add(-48 * time.Hour), End: date, Total: 3, Instead: []time.Time{date.Add(-72 * time.Hour)}, LegalDays: 1, } case 4: return Holiday{ Core: date, Start: date, End: date.Add(48 * time.Hour), Total: 3, Instead: []time.Time{date.Add(72 * time.Hour)}, LegalDays: 1, } } return Holiday{} } func target5Day1(date time.Time) Holiday { switch date.Weekday() { case 1: return Holiday{ Start: date.Add(time.Hour * -48), End: date.Add(time.Hour * 48), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * -24 * 8), date.Add(time.Hour * 24 * 5)}, Name: "", LegalDays: 1, } case 2: return Holiday{ Start: date, End: date.Add(time.Hour * -24 * 4), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * -24 * 2), date.Add(time.Hour * 24 * 5)}, Name: "", LegalDays: 1, } case 3: return Holiday{ Start: date, End: date.Add(time.Hour * 24 * 4), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * -24 * 3), date.Add(time.Hour * 24 * 10)}, Name: "", LegalDays: 1, } case 4: return Holiday{ Start: date, End: date.Add(time.Hour * 24 * 4), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * -24 * 4), date.Add(time.Hour * 24 * 9)}, Name: "", LegalDays: 1, } case 5: return Holiday{ Start: date, End: date.Add(time.Hour * 24 * 4), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * -24 * 5), date.Add(time.Hour * 24 * 8)}, Name: "", LegalDays: 1, } case 6: return Holiday{ Start: date, End: date.Add(time.Hour * 24 * 4), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * -24 * 6), date.Add(time.Hour * 24 * 7)}, Name: "", LegalDays: 1, } case 0: return Holiday{ Start: date.Add(time.Hour * -24), End: date.Add(time.Hour * 24 * 3), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * -24 * 7), date.Add(time.Hour * 24 * 6)}, Name: "", LegalDays: 1, } } return Holiday{} } func target5Day2(date time.Time) Holiday { switch date.Weekday() { case 1: return Holiday{ Start: date.Add(time.Hour * -48), End: date.Add(time.Hour * 48), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * 24 * 5)}, Name: "", LegalDays: 2, } case 2: return Holiday{ Start: date, End: date.Add(time.Hour * -24 * 4), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * -24 * 2)}, Name: "", LegalDays: 2, } case 3: return Holiday{ Start: date, End: date.Add(time.Hour * 24 * 4), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * -24 * 3)}, Name: "", LegalDays: 2, } case 4: return Holiday{ Start: date, End: date.Add(time.Hour * 24 * 4), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * -24 * 4)}, Name: "", LegalDays: 2, } case 5: return Holiday{ Start: date, End: date.Add(time.Hour * 24 * 4), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * 24 * 8)}, Name: "", LegalDays: 2, } case 6: return Holiday{ Start: date, End: date.Add(time.Hour * 24 * 4), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * 24 * 7)}, Name: "", LegalDays: 2, } case 0: return Holiday{ Start: date.Add(time.Hour * -24), End: date.Add(time.Hour * 24 * 3), Core: date, Total: 5, Instead: []time.Time{date.Add(time.Hour * 24 * 6)}, Name: "", LegalDays: 2, } } return Holiday{} } func target7Day3(date time.Time) Holiday { switch date.Weekday() { case 1: return Holiday{ Start: date, End: date.Add(time.Hour * 6 * 24), Core: date, Total: 7, Instead: []time.Time{date.Add(time.Hour * 24 * -2), date.Add(time.Hour * 24 * -1)}, Name: "", LegalDays: 3, } case 2: return Holiday{ Start: date, End: date.Add(time.Hour * 6 * 24), Core: date, Total: 7, Instead: []time.Time{date.Add(time.Hour * 24 * -2), date.Add(time.Hour * 24 * 11)}, Name: "", LegalDays: 3, } case 3: return Holiday{ Start: date, End: date.Add(time.Hour * 6 * 24), Core: date, Total: 7, Instead: []time.Time{date.Add(time.Hour * 24 * -3), date.Add(time.Hour * 24 * 10)}, Name: "", LegalDays: 3, } case 4: return Holiday{ Start: date, End: date.Add(time.Hour * 6 * 24), Core: date, Total: 7, Instead: []time.Time{date.Add(time.Hour * 24 * -4), date.Add(time.Hour * 24 * 9)}, Name: "", LegalDays: 3, } case 5: return Holiday{ Start: date, End: date.Add(time.Hour * 6 * 24), Core: date, Total: 7, Instead: []time.Time{date.Add(time.Hour * 24 * -5), date.Add(time.Hour * 24 * 8)}, Name: "", LegalDays: 3, } case 6: return Holiday{ Start: date, End: date.Add(time.Hour * 6 * 24), Core: date, Total: 7, Instead: []time.Time{date.Add(time.Hour * 24 * 7), date.Add(time.Hour * 24 * 8)}, Name: "", LegalDays: 3, } case 0: return Holiday{ Start: date, End: date.Add(time.Hour * 6 * 24), Core: date, Total: 7, Instead: []time.Time{date.Add(time.Hour * 24 * -1), date.Add(time.Hour * 24 * 7)}, Name: "", LegalDays: 3, } } return Holiday{} } func target8Day4(date time.Time) Holiday { switch date.Weekday() { case 1: return Holiday{ Start: date, End: date.Add(time.Hour * 7 * 24), Core: date, Total: 8, Instead: []time.Time{date.Add(time.Hour * 24 * -2), date.Add(time.Hour * 24 * -1)}, Name: "", LegalDays: 4, } case 2: return Holiday{ Start: date, End: date.Add(time.Hour * 7 * 24), Core: date, Total: 8, Instead: []time.Time{date.Add(time.Hour * 24 * -2), date.Add(time.Hour * 24 * 11)}, Name: "", LegalDays: 4, } case 3: return Holiday{ Start: date, End: date.Add(time.Hour * 7 * 24), Core: date, Total: 8, Instead: []time.Time{date.Add(time.Hour * 24 * -3), date.Add(time.Hour * 24 * 10)}, Name: "", LegalDays: 4, } case 4: return Holiday{ Start: date, End: date.Add(time.Hour * 7 * 24), Core: date, Total: 8, Instead: []time.Time{date.Add(time.Hour * 24 * -4), date.Add(time.Hour * 24 * 9)}, Name: "", LegalDays: 4, } case 5: if date.Year() >= 2025 { return Holiday{ Start: date, End: date.Add(time.Hour * 8 * 24), Core: date, Total: 9, Instead: []time.Time{date.Add(time.Hour * 24 * -5), date.Add(time.Hour * 24 * 9)}, Name: "", LegalDays: 4, } } return Holiday{ Start: date, End: date.Add(time.Hour * 7 * 24), Core: date, Total: 8, Instead: []time.Time{date.Add(time.Hour * 24 * 8), date.Add(time.Hour * 24 * 9)}, Name: "", LegalDays: 4, } case 6: return Holiday{ Start: date, End: date.Add(time.Hour * 7 * 24), Core: date, Total: 8, Instead: []time.Time{date.Add(time.Hour * 24 * -6), date.Add(time.Hour * 24 * 8)}, Name: "", LegalDays: 2, } case 0: return Holiday{ Start: date, End: date.Add(time.Hour * 7 * 24), Core: date, Total: 8, Instead: []time.Time{date.Add(time.Hour * 24 * -1)}, Name: "", LegalDays: 2, } } return Holiday{} } // 元旦 func YuanDan(year int) Holiday { name := "元旦" date := time.Date(year, 1, 1, 0, 0, 0, 0, time.Local) if year > 2007 || year == 2005 { d := target3Day1(date) d.Name = name return d } switch year { case 2007: return Holiday{ Start: date, End: date.Add(3 * 24 * time.Hour), Core: date, Total: 3, Instead: []time.Time{date.Add(-24 * time.Hour), date.Add(-2 * 24 * time.Hour)}, Name: name, LegalDays: 1, } case 2006: return Holiday{ Start: date, End: date.Add(3 * 24 * time.Hour), Core: date, Total: 3, Instead: []time.Time{date.Add(-24 * time.Hour)}, Name: name, LegalDays: 1, } case 2004, 2003: return Holiday{ Start: date, End: date, Core: date, Total: 1, Instead: nil, Name: name, LegalDays: 1, } case 2002: return Holiday{ Start: date, End: date.Add(3 * 24 * time.Hour), Core: date, Total: 3, Instead: []time.Time{date.Add(-3 * 24 * time.Hour), date.Add(-2 * 24 * time.Hour)}, Name: name, LegalDays: 1, } } return Holiday{Name: name} } // 春节 func ChunJie(year int) Holiday { name := "春节" chineseNewYear := calendar.RapidLunarToSolar(year, 1, 1, false) chuxi := chineseNewYear.AddDate(0, 0, -1) if year <= 2007 || year == 2014 { d := target7Day3(chineseNewYear) d.Name = name return d } if year >= 2008 && year < 2024 { d := target7Day3(chuxi) d.Name = name if year == 2020 { d.Comment = "因新冠疫情防控,2020年春节延长至2月2日" } return d } if year == 2024 { d := target8Day4(chineseNewYear) d.LegalDays = 3 d.Name = name return d } d := target8Day4(chuxi) d.Name = name return d } func QingMing(year int) Holiday { name := "清明节" if year < 2008 { return Holiday{Name: name} } qingming := calendar.JieQi(year, calendar.JQ_清明) d := target3Day1(qingming) d.Name = name return d } func LaoDongJie(year int) Holiday { name := "劳动节" date := time.Date(year, 5, 1, 0, 0, 0, 0, time.Local) if year < 2008 { d := target7Day3(date) d.Name = name return d } if year == 2019 { return Holiday{ Start: date, End: date.Add(4 * 24 * time.Hour), Core: date, Total: 4, Instead: []time.Time{date.Add(-24 * 3 * time.Hour), date.Add(24 * time.Hour * 5)}, Name: name, LegalDays: 1, Comment: "", } } if year >= 2008 && year < 2020 { d := target3Day1(date) d.Name = name return d } if year >= 2020 && year < 2025 { d := target5Day1(date) d.Name = name return d } d := target5Day2(date) d.Name = name return d } func DuanWu(year int) Holiday { name := "端午节" if year < 2008 { return Holiday{Name: name} } date := calendar.RapidLunarToSolar(year, 5, 5, false) d := target3Day1(date) d.Name = name return d } func ZhongQiu(year int) Holiday { name := "中秋节" if year < 2008 { return Holiday{Name: name} } date := calendar.RapidLunarToSolar(year, 8, 15, false) if date.Month() == 9 && date.Day() >= 28 { d := target8Day4(date) d.Name = "国庆中秋连假" return d } else if date.Month() == 10 { d := target8Day4(time.Date(year, 10, 1, 0, 0, 0, 0, time.Local)) d.Name = "国庆中秋连假" return d } d := target3Day1(date) d.Name = name if date.Month() == 9 && date.Day() <= 20 { return d } if date.Weekday() == 3 { d.Instead = []time.Time{date.Add(-24 * 3 * time.Hour), date.Add(24 * 3 * time.Hour)} d.End = date.Add(2 * 24 * time.Hour) d.Total = 3 } gq := target7Day3(time.Date(year, 10, 1, 0, 0, 0, 0, time.Local)) for _, v := range gq.Instead { if v.Before(d.End) || v.Equal(d.End) { if v.Equal(date) { d.Total = d.Total - 1 d.End = d.End.Add(-24 * time.Hour) } else { if v.Equal(d.Start) { d.Total = d.Total - 1 d.Start = d.Start.Add(24 * time.Hour) } else if v.Equal(d.End) { d.Total = d.Total - 1 d.End = d.End.Add(-24 * time.Hour) } } } } return d } func GuoQing(year int) Holiday { name := "国庆节" date := time.Date(year, 10, 1, 0, 0, 0, 0, time.Local) zq := calendar.RapidLunarToSolar(year, 8, 15, false) if year == 2008 { return Holiday{ Start: date.Add(-24 * 2 * time.Hour), End: date.Add(4 * 24 * time.Hour), Core: date, Total: 7, Instead: []time.Time{date.Add(-24 * 4 * time.Hour), date.Add(24 * -3 * time.Hour)}, Name: name, LegalDays: 3, } } if year < 2008 || (zq.Month() == 9 && zq.Day() <= 20) { d := target7Day3(date) d.Name = name return d } if zq.Month() == 9 && zq.Day() >= 28 { d := target8Day4(zq) d.Name = "国庆中秋连假" return d } else if zq.Month() == 10 { d := target8Day4(date) d.Name = "国庆中秋连假" return d } zqd := target3Day1(zq) if date.Weekday() == 3 { zqd.Instead = []time.Time{date.Add(-24 * 3 * time.Hour), date.Add(24 * 3 * time.Hour)} zqd.End = date.Add(2 * 24 * time.Hour) zqd.Total = 3 } d := target7Day3(date) d.Name = name for k, v := range d.Instead { if v.Before(zqd.End) || v.Equal(zqd.End) { if v.Equal(zq) { d.Instead = append(d.Instead[:k], d.Instead[k+1:]...) } } } return d } func ChineseHoliday(year int) []Holiday { d := []Holiday{ YuanDan(year), ChunJie(year), QingMing(year), LaoDongJie(year), DuanWu(year), ZhongQiu(year), GuoQing(year), } if d[len(d)-1].Name == "国庆中秋连假" { return d[:len(d)-1] } return d }