go多个时间区间之间(交集,并集, 差集)等操作包分享

项目地址

github.com/maogou/period

项目介绍

Period 是一个使用 Go 语言编的项目,主要用于处理和操作时间段。它提供了一系列的方法,如并集、交集、差集等,以便于用户对时间段进行各种操作。

⚠️ 警告:当前,Go(1.21.x) 语言还不支持枚举类型。如果 Go 语言在将来版本中支持枚举类型,我们将重构 bounds.go 文件中的方法。

英文介绍

典型应用场景

时间区间可以类比高中集合中的闭区间和开区间。例如,时间区间 [2023-12-09 08:00:00, 2023-12-09 14:23:45) 表示包含开始时间但不包含结束时间。

在生活中可能会遇到这样一个场景:您去大型商场购物,但该商场人流量大,停车位有限,因此一些人只能将车停在附近的马路边。
该马路边的停车收费区间为每天[08:00:00,21:00:00],并且在每天的高峰时段[10:00:00,12:00:00]和下午的[18:00:00,20:00:00]收费更高(4元/小时),其他时间段的收费为2元/小时。
比如说,您从2023-12-09 07:35:30进入该商场附近的马路边停车,然后准备在同一天下午2023-12-09 19:34:20离开。

如果情况更加复杂,马路边的管理者还出台了一项优惠政策:只要车主停车满4小时,就会随机发放一张优惠券。对于电子优惠券而言,它也有自己有效的时间区间范围[2023-12-09 16:30:23,2023-12-09 19:00:00]。

最终,您需要支付的停车费用是多少呢?针对这种情况,我们需要对多个时间区间进行交集、差集、并集等相关操作,并进行计算。

主要功能

  • 创建时间段:用户可以创建一个时间段,包括开始时间和结束时间。
  • 时间段并集:用户可以计算两个或多个时间段的并集。
  • 时间段交集:用户可以计算两个或多个时间段的交集。
  • 时间段差集:用户可以计算两个时间段的差集。

如何使用

首先,你需要在你的 Go 项目中引入 Period 项目。你可以在你的 go.mod 文件中添加以下依赖:

require (
    github.com/maogou/period v1.0.0
)

然后,你可以在你的代码中引入 Period 项目,并使用它提供的方法。以下是一个简单的示例:

package main

import (
    "github.com/maogou/period"
    "time"
)

func main() {
    p1 := period.Period{
        startDate:    time.Date(2023, 1, 1, 0, 0, 0, 0, time.Local),
        endDate:      time.Date(2023, 1, 3, 0, 0, 0, 0, time.Local),
        boundaryType: period.IncludeStartExcludeEnd,
    }

    p2 := period.Period{
        startDate:    time.Date(2023, 1, 2, 0, 0, 0, 0, time.Local),
        endDate:      time.Date(2023, 1, 4, 0, 0, 0, 0, time.Local),
        boundaryType: period.IncludeStartExcludeEnd,
    }

    result := p1.Union(p2)
    fmt.Println(result)
}

方法

以下是 Period 结构体的主要方法:

  • GetTimestampInterval(): 返回时间段的时间戳间隔。
  • Subtract(Period): 从当前时间段中减去另一个时间段,返回一个新的时间段。
  • Merge(Period): 合并当前时间段和另一个时间段,返回一个新的时间段。
  • Intersect(Period): 返回当前时间段和另一个时间段的交集。
  • Overlaps(Period): 判断当前时间段是否与另一个时间段重叠。
  • Abuts(Period): 判断当前时间段是否与另一个时间段相邻。
  • Contains(Period): 判断当前时间段是否包含另一个时间段。
  • Equals(Period): 判断当前时间段是否等于另一个时间段。
  • Gap(Period): 返回当前时间段和另一个时间段之间的间隙。
  • Diff(Period): 返回当前时间段和另一个时间段的差异。
  • Union(Period...): 获取当时时间段集合的并集。
  • IsZero(): 判断当前时间段是否为零。

以下是 Sequence 结构体的主要方法:

  • NewSequence(Period...): 创建一个新的时间段序列。
  • totalTimeDuration(): 返回时间段序列的总时间长度。
  • GetTotalTimestampInterval(): 返回时间段序列的总时间戳间隔。
  • Sort(func(Period, Period) bool): 根据给定的比较函数对时间段序列进行排序。
  • Contains(Period...): 判断时间段序列是否包含给定的时间段。
  • Subtract(Sequence): 从当前时间段序列中减去另一个时间段序列,返回一个新的时间段序列。
  • Equals(Sequence): 判断当前时间段序列是否等于另一个时间段序列。
  • Unions(): 返回时间段序列的并集。
  • Gaps(): 返回时间段序列的间隙。
  • IsEmpty(): 判断时间段序列是否为空。
  • IndexOf(Period): 返回给定时间段在时间段序列中的索引。
  • Count(): 返回时间段序列的数量。
  • Get(int): 返回时间段序列中给定索引的时间段。
  • Set(int, Period): 在时间段序列的给定索引处设置时间段。
  • Push(Period...): 在时间段序列的末尾添加时间段。
  • Intersections(): 返回时间段序列的交集。
  • Remove(int): 移除时间段序列中给定索引的时间段。
  • Filter(func(Period) bool): 根据给定的过滤函数过滤时间段序列。
  • Map(func(Period) Period): 根据给定的映射函数映射时间段序列。
  • Every(func(Period, int) bool): 判断时间段序列是否每个元素都满足给定的条件。
  • Some(func(Period, int) bool): 判断时间段序列是否有元素满足给定的条件。
  • Clear(): 清空时间段序列。

测试

Period 项目包含一系列的单元测试,以确保代码的质量和功能的正确性。你可以通过运行以下命令来执行这些测试:

go test ./... -v -count=1

代码覆盖率(100%)

我们使用 Go 的内置测试工具来跟踪代码覆盖率。你可以通过以下步骤生成和查看覆盖率报告:

 go test ./... -coverprofile=coverage.out && go tool cover -html=coverage.out

贡献

我们欢迎任何形式的贡献,包括但不限于提交问题、提供反馈、提出新的功能建议、改进代码等。如果你有任何问题或建议,欢迎在 GitHub 上提交 issue 或 pull request。

许可证

Period 项目采用 MIT 许可证,详情请参见 LICENSE 文件。

kinyou
讨论数量: 7

话说,go已经支持枚举了的。搜一下

4个月前 评论
kinyou (楼主) 4个月前
deatil (作者) 4个月前
yanthink 4个月前
kinyou

@deatil 我说的枚举是go原生枚举类型, 可以做函数参数限定等等, 你可以参考一下php的枚举, 我想要的就是php这样的效果,而 你给的示例是一种变现的枚举类型的实现, 但是不能用作参数限定
如果我定义一个函数 func demo(enum xxxx) { //那么我这样写, 我希望xxxx是被枚举参数限定的, 只能是1或者2或者3 这三个值的其中之一 }

www.php.net/manual/zh/language.enu...

file

4个月前 评论
deatil 4个月前
kinyou (作者) (楼主) 4个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!