『自己构建节假日API』

RickAndMorty.png

大家好,我叫谢伟,是一名程序员。

之前梳理了一些内置库的学习,收到了一些评论,绝大多数评论都在直指一个问题:为什么梳理这些无关痛痒的内置库?

好吧,看上去确实都是些简单的内置库的梳理。主要原因是为了:《后端工程师的攻略》这个系列,从零起步,教程到这个地步,看上去是需要提高难度了。后续加以改善。另外一个原因,其实是想告诉初学者,内置库的很多代码组织方式,代码的编写方式指的学习、借鉴、参考。

这期是我之前准备的,趁着这期还是放送出来吧。

核心很简单:懂 Go 的基本语法,会使用内置库的 time, 基本能搞到这些。

大纲:

前段日子项目中需要使用的国家规定的节假日,所以需要获取这些数据。其实获取这些数据的方式也很多:

  • 比如比较笨的方式:搜索引擎,手动整理
  • 使用一些免费开放的第三方节假日 API: 不稳定,虽然这些数据也不需要频繁的使用
  • 使用一些付费的第三方节假日 API:付费

于是本着简洁的方式,编写这么一个节假日的库。

要求:

  • 简单的功能
  • 简单的API

1. 数据获取

数据源需要可靠,所以需要寻找官方的通知来源。

比如:国务院办公厅关于2018年部分节假日安排的通知

一般的方式呢,就是网页数据抓取,解析出得到的数据。

这是第一步,获取数据;当然,很多网站都可以找到这些信息,这里仅仅举例。

2. 定义结构体

关于节假日,我们最需要知道的是什么信息?

  • 名称
  • 时间安排

基于此,可以这么设计结构体:

type OneCollection struct {
    Start  string `json:"start"`
    End    string `json:"end"`
    ChName string `json:"ch_name"`
    EnName string `json:"en_name"`
}

包括:

  • 中文名称
  • 英文名称
  • 开始时间
  • 结束时间

关于节假日名称呢,国家法定的节日是这么几个:元旦、春节、清明、端午、劳动、中秋、国庆

借鉴许多内置库的处理方式:这种固定的数据的处理,可以使用枚举类型:

const (
    NewYearDay = iota
    SpringFestivalDay
    TombSweepingDay
    LaborDay
    DragonBoatFestivalDay
    NationalDay
    MidAutumnFestivalDay
)

var ChHolidays = [...]string{
    "元旦",
    "春节",
    "清明节",
    "劳动节",
    "端午节",
    "中秋节",
    "国庆节",
}
var EnHolidays = [...]string{
    "New Year\\'s Day",
    "Spring Festival",
    "Tomb-sweeping Day",
    "Labour Day",
    "Dragon Boat Festival",
    "Mid-autumn Festival",
    "National Day",
}

中英文,获取指定偏移量上的数据即可,这种处理方式在内置库很常见:比如时间类型的时间基本单位月:一月、二月、三月等

3. 历史数据

基于上文的分析,要构建这个简单的库,要组织历史节假日,这边选取 2010年到 2019 年的数据。

// 一年
type YearCollection struct {
    Data []OneCollection `json:"data"`
}
// n 年
type CollectionYearHistory struct {
    Data [][]OneCollection `json:"data"`
}

// 2010 年到 2019年历史数据
func FetchCollectionYearHistory() CollectionYearHistory {
    return CollectionYearHistory{
        Data: [][]OneCollection{
            holiday2019,
            holiday2018,
            holiday2017,
            holiday2016,
            holiday2015,
            holiday2014,
            holiday2013,
            holiday2012,
            holiday2011,
            holiday2010,
        },
    }
}

4. 构建API

  • 选择好的命名方式
  • 选择好的数据返回格式
- FetchAll
- FetchByChName(year int, name string)
- FetchByEnName(year int, name string)
- FetchByMonth(year int, month int)
- FetchByYear(year int)
- FetchMonthHolidayCount(year int, month int)
- FetchYearHolidayCount(year int)
- IsHoliday
- IsWeekDay
- IsWorkDay

之所以这样设计, 是因为项目中经常会是这样的操作:

  • 获取所有的历史数据
  • 获取某年的历史数据
  • 获取某月的历史数据
  • 统计某年某月的放假天数
  • 统计某年的放假天数
  • 判断一个日期是否是节假日
  • 判断一个日期是否是周末
  • 判断一个日期是否是工作日

基于这些需求,构建了上文的API

以几个API 为例,详细的操作如何实现?

  • FetchByYear(year int): 从历史数据中获取
// FetchByYear get holidays by year in china
func FetchByYear(year int) []history.OneCollection {
    var index int
    nowYear, _, _ := time.Now().Date()
    if year > nowYear+1 {
        return nil
    }
    index = nowYear + 1 - year
    return history.FetchCollectionYearHistory().Data[index]

}
  • FetchByMonth: 从某年的历史数据中获取
func FetchByMonth(year int, month int) []history.OneCollection {
    if month < 1 || month > 12 {
        return nil

    }
    collections := FetchByYear(year)
    var data []history.OneCollection
    for _, collection := range collections {
        collectionTime, _ := time.Parse("2006/01/02", collection.End)
        if int(collectionTime.Month()) == month {
            data = append(data, collection)
        }
    }
    return data
}
  • IsHoliday: 历史数据中是否能击中目标
func IsHoliday(value string) bool {
    collectionTime, err := time.Parse("2006/01/02", value)
    if err != nil {
        return false
    }
    nowYear, _, _ := time.Now().Date()
    if collectionTime.Year() > nowYear+1 {
        return false
    }
    collections := FetchByYear(collectionTime.Year())
    for _, collection := range collections {
        startDate, _ := getDate(collection.Start)
        endDate, _ := getDate(collection.End)
        if collectionTime.Unix() >= startDate.Unix() && collectionTime.Unix() <= endDate.Unix() {
            return true
        }
    }
    return false

}
  • IsWeekDay: 不是节假日、也不是工作日的
// IsWeekDay: judge date is week day or not
func IsWeekDay(value string) bool {
    return !IsWorkDay(value) && !IsHoliday(value)
}

<后记>

基于上文的理念,其实可以写很多小工具:

比如:

  • 获取古诗词
  • 给定一个日期,判断星座
  • 给定一个身份证,判断是否有效,属于哪个地区等
  • 给定一个ip, 给出地理位置
  • 给定一个中文,给出英文或者拼音
  • 给定文字,解释其中文含义
    ...

<完>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容

  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,938评论 2 89
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,672评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,185评论 25 707
  • 我的寒假生活,照顾小弟是必不可少的!早上起床,刷好牙洗好脸,逗床上的小弟,妈妈做早餐!吃好早饭,妈妈干家务...
    米兰叮当阅读 203评论 0 0
  • 当开始发现对所有堕落的方式都提不起兴趣的时候,应该就可以说明,已经不想堕落了吧,那么下一件事情就是重新起步了。 《...
    琢一阅读 1,028评论 0 0