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

关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力!

在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函数,我们确保了准确的计算。

获取每周的开始日和结束日

获取每周的开始日

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秒

上述函数接受一个持续时间,返回一个格式化的字符串,以便更友好地显示。这对于向用户呈现持续时间时非常实用。

通过使用这些高级实用函数,我们扩展了日期时间包装器的功能,为开发人员提供了一套全面的工具来处理各种与时间相关的操作。这些函数可以轻松集成到您的代码库中,简化了复杂的日期和时间操作,无论是构建计划应用程序、生成报告,还是处理各种时间敏感的任务。

相关推荐
用户342323237631710 小时前
开源!Go+Wails+Vue3 手搓一个 PLC 实时监控桌面工具
go
止语Lab10 小时前
为什么你的 Go TCP server P99 延迟这么高
go
Andy Dennis17 小时前
nsq学习记录
消息队列·go·nsq
韦胖漫谈IT19 小时前
选语言不是站队,是选适合问题的工具
java·python·ai·rust·go·技术落地
喵个咪1 天前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm
夜悊1 天前
Go网络编程的学习代码示例:客户端/服务端(C/S)模型
go
审判长烧鸡2 天前
【AI问答】GO代码循环返值
go
捧 花2 天前
Eino框架记忆功能实现指南
go·agent·eino
Java陈序员2 天前
主流数据库通吃!一款开源实用的数据库备份管理工具!
react.js·postgresql·go
云浪2 天前
搞懂 Go WaitGroup:一篇文章彻底理解并发等待机制
后端·go