You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
star/astro/chineseday.go

692 lines
16 KiB
Go

5 days ago
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
}