package holiday import ( "bytes" "encoding/json" "errors" "fmt" "github.com/fonchain_enterprise/fonchain-main/pkg/cache" "github.com/fonchain_enterprise/fonchain-main/pkg/config" "github.com/fonchain_enterprise/fonchain-main/pkg/e" "go.uber.org/zap" "io" "net/http" "strconv" "strings" "time" ) type HolidayDate struct { Date string `json:"date"` WeekDay int8 `json:"weekDay"` YearTips string `json:"yearTips"` Type int8 `json:"type"` TypeDes string `json:"typeDes"` ChineseZodiac string `json:"chineseZodiac"` SolarTerms string `json:"solarTerms"` Avoid string `json:"avoid"` LunarCalendar string `json:"lunarCalendar"` Suit string `json:"suit"` DayOfYear int16 `json:"dayOfYear"` WeekOfYear int16 `json:"weekOfYear"` Constellation string `json:"constellation"` IndexWorkDayOfMonth int8 `json:"indexWorkDayOfMonth"` } type HolidayInfoReq struct { BeginDate string `json:"beginDate"` EndDate string `json:"endDate"` } type SingleHolidayResp struct { Code int8 `json:"code"` Msg string `json:"msg"` Data HolidayDate `json:"data"` } type MultiHolidayResp struct { Code int8 `json:"code"` Msg string `json:"msg"` Data []HolidayDate `json:"data"` } type RespData struct { IsToday bool `json:"isToday,default:false"` // 是否是今天 IsOtherMonthDay bool `json:"isOtherMonthDay,default:true"` // 是否是其他月份的日期 Day int8 `json:"day"` Month int8 `json:"month"` Type int8 `json:"type"` // 0 工作日 1 假日 2 节假日 WeekDay int8 `json:"weekDay"` RenderMonth int8 `json:"renderMonth"` RenderYear int32 `json:"renderYear"` Year int32 `json:"year"` TypeDes string `json:"typeDes"` Lunar string `json:"lunar"` // 农历 } var ( IsStartFromZERO = true ) // 万年历 func GetSingleData(date string, ignoreHoliday bool) (*RespData, error) { if v, err := GetCacheHolidayInfo([]string{date}); err == nil && len(v) > 0 { fmt.Println("go to cache ") return v[len(v)-len(v)], nil } resp, err := http.Get(fmt.Sprintf(config.HolidaySingleUrl, date, ignoreHoliday, config.HolidayID, config.HolidaySecret)) if err != nil { return nil, err } defer resp.Body.Close() bt := make([]byte, 0) buf := bytes.NewBuffer(bt) io.Copy(buf, resp.Body) holidayResp := SingleHolidayResp{} err = json.Unmarshal(buf.Bytes(), &holidayResp) if err != nil { return nil, err } data := dataHandle([]HolidayDate{holidayResp.Data}, []string{date}) if len(data) == 1 { return data[0], nil } else { return nil, errors.New("操作失败") } } func GetMultiData(beginDate, endDate string, ignoreHoliday bool) ([]*RespData, error) { dates := SplitDates(beginDate, endDate, "20060102") //fmt.Println(dates) if v, err := GetCacheHolidayInfo(dates); err == nil && len(v) > 0 { fmt.Println("go to cache ") return v, nil } fmt.Println(fmt.Sprintf(config.HolidayMultiUrl, strings.Join(dates, ","), ignoreHoliday, config.HolidayID, config.HolidaySecret)) //time.Sleep(100 * time.Nanosecond) resp, err := http.Get(fmt.Sprintf(config.HolidayMultiUrl, strings.Join(dates, ","), ignoreHoliday, config.HolidayID, config.HolidaySecret)) if err != nil { return nil, err } defer resp.Body.Close() bt := make([]byte, 0) buf := bytes.NewBuffer(bt) io.Copy(buf, resp.Body) holidayResp := new(MultiHolidayResp) holidayResp.Data = make([]HolidayDate, 0) err = json.Unmarshal(buf.Bytes(), &holidayResp) if err != nil { return nil, err } fmt.Println(holidayResp.Data) holidayMap := make(map[string]interface{}, 0) for i := 0; i < len(holidayResp.Data); i++ { bt, _ := json.Marshal(holidayResp.Data[i]) holidayMap[ConvertTime(holidayResp.Data[i].Date)] = bt } // 缓存 日历信息 cache.HMSet(cache.HolidayMap, holidayMap) data := dataHandle(holidayResp.Data, dates) fmt.Println(data) if len(data) > 0 { return data, nil } else { return nil, errors.New("操作失败") } } func dataHandle(holidayDate []HolidayDate, dates []string) []*RespData { respDatas := make([]*RespData, 0) for i := 0; i < len(holidayDate); i++ { respData := &RespData{} if holidayDate[i].Date == time.Now().Format("2006-01-02") { respData.IsToday = true } for j := 0; j < len(dates); j++ { if strings.Replace(holidayDate[i].Date, "-", "", -1) == dates[j] { dateArray := strings.Split(dates[j], "") year, _ := strconv.Atoi(strings.Join(dateArray[0:4], "")) respData.Year = int32(year) month, _ := strconv.Atoi(strings.Join(dateArray[4:6], "")) respData.Month = int8(month) day, _ := strconv.Atoi(strings.Join(dateArray[6:8], "")) respData.Day = int8(day) } } respData.RenderYear = int32(time.Now().Year()) respData.RenderMonth = int8(time.Now().Month()) if respData.RenderYear != respData.Year || respData.RenderMonth != respData.Month { respData.IsOtherMonthDay = true } respData.Lunar = holidayDate[i].LunarCalendar respData.WeekDay = holidayDate[i].WeekDay respData.Type = holidayDate[i].Type //if respData.Type >= 1 { // // respData.Type = 1 //} respData.TypeDes = holidayDate[i].TypeDes respDatas = append(respDatas, respData) } return respDatas } func SplitDates(beginDate, endDate, format string) []string { bDate, _ := time.ParseInLocation(format, beginDate, time.Local) eDate, _ := time.ParseInLocation(format, endDate, time.Local) if bDate == eDate { return []string{bDate.Format(format)} } day := int(eDate.Sub(bDate).Hours() / 24) dlist := make([]string, 0) dlist = append(dlist, beginDate) for i := 1; i < day; i++ { result := bDate.AddDate(0, 0, i) dlist = append(dlist, result.Format(format)) } dlist = append(dlist, endDate) return dlist } // 格式 2023-01-01 func SplitMonth(month string, format string) []string { bDate, _ := time.ParseInLocation(format, month, time.Local) bDate = bDate.AddDate(0, 1, 0) eDate := bDate.AddDate(0, 0, -1) return SplitDates(month, eDate.Format(format), format) } func GetCommonWorkDays(days []*RespData, m map[int]int) []*RespData { workDays := make([]*RespData, 0) for i := 0; i < len(days); i++ { _, ok := m[int(days[i].WeekDay)] if ok { // m 不为 nil 则使用 m 的规则 //workDays = append(workDays, days[i]) if days[i].Type == 0 { workDays = append(workDays, days[i]) } } else if days[i].Type == 0 { // m 为 nil 则使用 正常工作日 的规则 workDays = append(workDays, days[i]) } } return workDays } func ConvertTime(t string) string { ts := strings.Split(t, "-") for i := 1; i < len(ts); i++ { if s, err := strconv.Atoi(ts[i]); err == nil { if s < 10 { //fmt.Println(s) ts[i] = "0" + strconv.Itoa(s) //fmt.Println(ts[i]) } } } return strings.Join(ts, "") } func GetCacheHolidayInfo(date []string) (value []*RespData, err error) { v, err := cache.HMGet(cache.HolidayMap, date...) if err != nil { return nil, err } zap.L().Info("GetCacheHolidayInfo", zap.Any("redis client ", cache.RedisClient.String())) fmt.Printf("redis client %+v\n", cache.RedisClient.String()) if len(v) == 0 { return nil, errors.New(e.ErrHolidayMiss) } holidayDates := make([]HolidayDate, 0) for i := 0; i < len(v); i++ { holidayDate := HolidayDate{} if v[i] == nil { return nil, errors.New(e.ErrHolidayMiss) } json.Unmarshal([]byte(v[i].(string)), &holidayDate) holidayDates = append(holidayDates, holidayDate) zap.L().Info("holiday list ", zap.Any("holiday list ", fmt.Sprintf(" v: %+v", holidayDate))) fmt.Printf("holiday list %+v\n", holidayDate) } return dataHandle(holidayDates, date), nil } func CurrentWeek(t time.Time) (string, string) { if t.Weekday() == time.Monday { return t.Format("2006-01-02"), t.AddDate(0, 0, 6).Format("2006-01-02") } else if t.Weekday() == time.Sunday { return t.AddDate(0, 0, -6).Format("2006-01-02"), t.Format("2006-01-02") } else { return t.AddDate(0, 0, -int(t.Weekday())+1).Format("2006-01-02"), t.AddDate(0, 0, -int(t.Weekday())+1).AddDate(0, 0, 6).Format("2006-01-02") } } // 格式 2023-01-26 ~ 2023-02-25 func SplitMonthV1(month string, format string) []string { bDate, _ := time.ParseInLocation(format, month, time.Local) bDate = bDate.AddDate(0, -1, 0) sDate := bDate.AddDate(0, 0, 1) return SplitDates(sDate.Format(format), month, format) } func CurrentMonth() string { t := time.Now() var month string // 25号之后属于下个月 if t.Day() > 25 { tt, _ := time.ParseInLocation("2006-01", t.Format("2006-01"), time.Local) month = tt.AddDate(0, 1, 0).Format("2006-01") } else if t.Day() <= 25 { month = t.Format("2006-01") } return month } func NextDate() string { return time.Now().AddDate(0, 0, 1).Format("2006-01-02") }