Go 日期时间包装器:15条更便捷的时间处理

TimLiuDream · · 921 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

> 关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力! 在Go编程中,处理日期和时间是一项常见任务,涉及到精确性和灵活性。尽管Go的标准库提供了时间包(`time`)用于处理时间相关操作,但在某些情况下,我们需要额外的实用函数来简化这些任务。本文将介绍一系列实用函数,它们充当`time`包的包装器,提供了更便捷的操作方式。 ## 获取月初和月底 ### 获取月初 ```go func StartOfMonth(date time.Time) time.Time { return time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, date.Location()) } // output: 2024-01-01 00:00:00 +0800 CST ``` 上述函数接受一个日期,返回该日期所在月份的第一天。例如,`StartOfMonth(time.Now())`将返回当前月份的第一天的时间戳。 ### 获取月底 ```go func EndOfMonth(date time.Time) time.Time { firstDayOfNextMonth := StartOfMonth(date).AddDate(0, 1, 0) return firstDayOfNextMonth.Add(-time.Second) } // output: 2024-01-31 23:59:59 +0800 CST ``` 上述函数接受一个日期,返回该日期所在月份的最后一天的最后一秒。通过结合`StartOfMonth`函数,我们确保了准确的计算。 ![大号个人微信号已裁剪.png](https://static.golangjob.cn/240120/16524fea978d68a9adc5f88471236e90.png) ## 获取每周的开始日和结束日 ### 获取每周的开始日 ```go func StartOfDayOfWeek(date time.Time) time.Time { daysSinceSunday := int(date.Weekday()) return date.AddDate(0, 0, -daysSinceSunday+1) } // output: 2024-01-15 00:19:42.869678 +0800 CST ``` 上述函数接受一个日期,返回该日期所在周的第一天。 ### 获取每周的结束日 ```go func EndOfDayOfWeek(date time.Time) time.Time { daysUntilSaturday := 7 - int(date.Weekday()) return date.AddDate(0, 0, daysUntilSaturday) } // output: 2024-01-21 00:22:06.955558 +0800 CST ``` 上述函数接受一个日期,返回该日期所在周的最后一天。 ## 获取给定月份每周的开始日和结束日 ```go func StartAndEndOfWeeksOfMonth(year, month int) []struct{ Start, End time.Time } { startOfMonth := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC) weeks := make([]struct{ Start, End time.Time }, 0) for current := startOfMonth; current.Month() == time.Month(month); current = current.AddDate(0, 0, 7) { startOfWeek := StartOfDayOfWeek(current) endOfWeek := EndOfDayOfWeek(current) if endOfWeek.Month() != time.Month(month) { endOfWeek = EndOfMonth(current) } weeks = append(weeks, struct{ Start, End time.Time }{startOfWeek, endOfWeek}) } return weeks } // output: [ {2024-01-01 00:00:00 +0000 UTC 2024-01-07 00:00:00 +0000 UTC} {2024-01-08 00:00:00 +0000 UTC 2024-01-14 00:00:00 +0000 UTC} {2024-01-15 00:00:00 +0000 UTC 2024-01-21 00:00:00 +0000 UTC} {2024-01-22 00:00:00 +0000 UTC 2024-01-28 00:00:00 +0000 UTC} {2024-01-29 00:00:00 +0000 UTC 2024-01-31 23:59:59 +0000 UTC} ] ``` 上述函数接受年份和月份,返回一个包含给定月份中每周的开始日和结束日的切片。通过调用前述的获取每周开始日和结束日的函数,我们得到了全面的每周视图。 ## 获取从日期开始的一个月的周数 ```go func WeekNumberInMonth(date time.Time) int { startOfMonth := StartOfMonth(date) _, week := date.ISOWeek() _, startWeek := startOfMonth.ISOWeek() return week - startWeek + 1 } // output: 3 ``` 上述函数接受一个日期,返回该日期所在月份的相对周数。通过利用ISO周数的概念,我们实现了简便的计算。 ## 获取新年伊始和年底 ### 获取新年伊始 ```go func StartOfYear(date time.Time) time.Time { return time.Date(date.Year(), time.January, 1, 0, 0, 0, 0, date.Location()) } // output: 2024-01-01 00:00:00 +0800 CST ``` 上述函数接受一个日期,返回该日期所在年份的第一天。 ### 获取年底 ```go func EndOfYear(date time.Time) time.Time { startOfNextYear := StartOfYear(date).AddDate(1, 0, 0) return startOfNextYear.Add(-time.Second) } // output: 2024-12-31 23:59:59 +0800 CST ``` 上述函数接受一个日期,返回该日期所在年份的最后一天的最后一秒。 ## 获取季度初数据和季度末 ### 获取季度初数据 ```go func StartOfQuarter(date time.Time) time.Time { // you can directly use 0, 1, 2, 3 quarter quarter := (int(date.Month()) - 1) / 3 startMonth := time.Month(quarter*3 + 1) return time.Date(date.Year(), startMonth, 1, 0, 0, 0, 0, date.Location()) } // output: 2024-01-01 00:00:00 +0800 CST ``` 上述函数接受一个日期,返回该日期所在季度的第一天。 ### 获取季度末 ```go func EndOfQuarter(date time.Time) time.Time { startOfNextQuarter := StartOfQuarter(date).AddDate(0, 3, 0) return startOfNextQuarter.Add(-time.Second) } // output: 2024-03-31 23:59:59 +0800 CST ``` 上述函数接受一个日期,返回该日期所在季度的最后一天的最后一秒。 ## 获取当前周范围 ```go func CurrentWeekRange(timeZone string) (startOfWeek, endOfWeek time.Time) { loc, _ := time.LoadLocation(timeZone) now := time.Now().In(loc) startOfWeek = StartOfDayOfWeek(now) endOfWeek = EndOfDayOfWeek(now) return startOfWeek, endOfWeek } // output: 2024-01-15 00:37:18.812985 +0800 CST 2024-01-21 00:37:18.812985 +0800 CST ``` 上述函数接受一个时区字符串,返回该时区中当前周的开始时间和结束时间。通过调用前述的获取每周开始日和结束日的函数,我们获得了当前周的范围。 ## 计算两个日期之间的持续时间 ```go func DurationBetween(start, end time.Time) time.Duration { return end.Sub(start) } // output: 10.000000101s ``` 上述函数接受两个日期,返回它们之间的持续时间。这个函数在测量两个事件之间经过的时间时非常有用。 ## 获取给定月份的星期几的日期 ```go func GetDatesForDayOfWeek(year, month int, day time.Weekday) []time.Time { var dates []time.Time firstDayOfMonth := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC) diff := int(day) - int(firstDayOfMonth.Weekday()) if diff < 0 { diff += 7 } firstDay := firstDayOfMonth.AddDate(0, 0, diff) for current := firstDay; current.Month() == time.Month(month); current = current.AddDate(0, 0, 7) { dates = append(dates, current) } return dates } // output: [2024-01-05 00:00:00 +0000 UTC 2024-01-12 00:00:00 +0000 UTC 2024-01-19 00:00:00 +0000 UTC 2024-01-26 00:00:00 +0000 UTC] ``` 上述函数接受年份、月份和目标星期几,返回给定月份中指定日期的所有出现情况。这为获取一个月中特定日期的出现提供了通用的解决方案。 ## 将工作日添加到日期 ```go func AddBusinessDays(startDate time.Time, daysToAdd int) time.Time { currentDate := startDate for i := 0; i < daysToAdd; { currentDate = currentDate.AddDate(0, 0, 1) if currentDate.Weekday() != time.Saturday && currentDate.Weekday() != time.Sunday { i++ } } return currentDate } // output: 2024-03-01 00:46:38.131747 +0800 CST ``` 上述函数接受一个起始日期和要添加的工作日数,返回加上指定工作日后的日期。这对于处理只涉及工作日的应用程序非常有用。 ## 将持续时间格式化为人类可读的字符串 ```go func FormatDuration(duration time.Duration) string { days := int(duration.Hours() / 24) hours := int(duration.Hours()) % 24 minutes := int(duration.Minutes()) % 60 seconds := int(duration.Seconds()) % 60 return fmt.Sprintf("%d天 %02d小时 %02d分 %02d秒", days, hours, minutes, seconds) } // output: 3天 04小时 15分 30秒 ``` 上述函数接受一个持续时间,返回一个格式化的字符串,以便更友好地显示。这对于向用户呈现持续时间时非常实用。 通过使用这些高级实用函数,我们扩展了日期时间包装器的功能,为开发人员提供了一套全面的工具来处理各种与时间相关的操作。这些函数可以轻松集成到您的代码库中,简化了复杂的日期和时间操作,无论是构建计划应用程序、生成报告,还是处理各种时间敏感的任务。

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

921 次点击  
加入收藏 微博
1 回复  |  直到 2024-11-26 15:28:18
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传