我正在参加中秋创意投稿大赛,详情请看:中秋创意投稿大赛
前言
关于这次中秋征文的内容,自己确实想了好久,因为作为一名后端研发工程师,不太想去搞一个酷炫的界面,感觉那是前端同学的蛋糕。想利用自己的技能优势,搞一波儿事情。同时又想有所创新,搞点别人没有搞过的,终于昨天确定了文章的内容——开发一款中秋节日历提醒服务,今天开始正式干活儿。
正文
本文介绍的中秋节日历提醒服务,主要有两个功能,一个提供主动查询能力,另一个是注册节日的回调通知。下面分别进行介绍。
主动查询
中秋节日历提醒服务提供了节日查询接口,通过调用查询接口,日历服务会根据当前的查询时间,返回当前时间是否为中秋假期。这里需要注意的一点是,服务没有根据客户端上传的时间去判断是否为中秋假期。而是根据服务器的时间,这样就避免了不同终端因为本地时钟偏差导致的查询结果不一致的问题。但是,这样也会导致另外一个问题,就是如果服务器的时钟不准了,那么查询结果就都不可靠了。所以,一定要保证服务器时钟状态的准确性,当然,这也是日历提醒服务工作的基础。
1. 准备节日数据集
中秋日历服务能够对外提供服务的前提是有节日数据,简单来说就是中秋节的具体日期。我们把数据集存储到文件 data.json 中,具体内容如下:
{
"中秋节": [
"2021-9-19"
],
"中秋": [
"2021-9-19"
]
}
复制代码
这里只罗列了中秋节的时间集,后期我们也可以继续扩展其他节日的查询能力,比如国庆节、元旦、端午节等。
2. 定义查询接口
中秋节日历提醒服务的接口 API :/:festival/:callback
接口类型:Get
服务器处理请求时,会根据参数 festival,确定要查询或者注册的节日类型,本文只讨论中秋节。其中,参数 callback 是回调通知的目标地址,具体解析逻辑如下:
r.GET("/:festival/:callback", func(ctx *gin.Context) {
fest := ctx.Param("festival")
cb := ctx.Param("callback")
if err := holiday.SetCallback(cb); err != nil {
ctx.String(http.StatusBadRequest, "%s", err.Error())
}
data, err := holiday.Query(fest)
if err != nil {
ctx.String(http.StatusBadRequest, "%s", err.Error())
} else {
ctx.JSON(http.StatusOK, data)
}
})
log.Fatal(r.Run(":3000"))
复制代码
3. 查询服务
当服务器接收到查询中秋节的服务时,会首先到节日数据集中去查询,如果没有给出的特定的提示。当存在节日数据集时,会校验当前查询时间和节日时间的时间差值,从而判断节日状态。
具体代码逻辑如下:
func Query(date string) (res []string, err error) {
// 解析具体节日类型,目前仅支持中秋节查询
day, ok := holidayCache[date]
if !ok {
return nil, errors.New("对不起,暂不支持该节日查询")
}
da := strings.Split(day[0], "-")
y, _ := strconv.Atoi(da[0])
m, _ := strconv.Atoi(da[1])
d, _ := strconv.Atoi(da[2])
// 计算当前时间和中秋节的天数差
now := time.Now()
dt1 := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 100, time.Local)
dt2 := time.Date(y, time.Month(m), d, 0, 0, 0, 100, time.Local)
sub := int(math.Ceil(dt2.Sub(dt1).Hours() / 24))
// 中秋三天假,会存在三个值
if sub == 0 || sub == -1 || sub == -2 {
msg := "今天是中秋节,好好享受假期吧!"
res = append(res, msg)
return res, nil
} else if sub > 0 {
msg := "还有" + strconv.Itoa(sub) + "天就中秋节啦,好好期待假期吧!"
res = append(res, msg)
return res, nil
} else {
msg := "今年中秋节已经过完啦,期待明年中秋节见!"
res = append(res, msg)
return res, nil
}
}
复制代码
4. 接口演示
下面通过不同的请求验证日历提醒服务的可用性。
1)正常请求
Get请求:http://127.0.0.1:3000/%E4%B8%AD%E7%A7%8B%E8%8A%82/192.168.166.6:3001
修改服务器时间为2021年9月19日(中秋节当天),因为服务部署在了本地,也就是修改本地时间。再调用查询接口,返回结果如下图所示:
如果把服务器时间调整到2021年10月1日(中秋节已经过完),再调用查询接口,返回结果如下图所示:
2)异常请求
Get请求:http://127.0.0.1:3000/%E5%9B%BD%E5%BA%86%E8%8A%82/192.168.166.6:3001
回调通知
注册中秋节日提醒回调通知,就是启动一个定时器,当中秋节时间到了,自动触发 http 回调通知,具体地址就是请求中的 callback 参数。原理和查询日历服务接口是一致的,内容就不展开了。
结尾
好了,一款中秋节日历提醒服务就开发完成了。稍后把中秋节提醒服务部署到公网上,就可以耐心等待【中秋赏月】的通知了。喜欢的小伙伴,给个赞吧,3ks!