Go – 从 ISO 年周获取一周的第一天的 Unix 时间戳。

huangapple go评论154阅读模式
英文:

Go - Unix timestamp for first day of the week from ISO year week

问题

获取2010年第五周星期一00:00:00的时间戳有什么好的方法?实际上,我正在寻找与time包中的ISOweek函数相反的函数。我似乎找不到实现这一目标的方法。Parse()函数无法读取周数,而且仅仅计算自年/月的第一天以来有多少个"7天"并不能满足我的需求。

非常感谢!
Bill

英文:

What's a good way of getting the timestamp for, say, the Monday 00:00:00 for the fifth week of 2010? Essentially I'm looking for the inverse function to ISOweek in the time package. I can't seem to find a way to achieve that. Parse() doesn't read week, and simply counting how many "7 days" there have been since the first day of the year/month doesn't really get me what I need.

Thanks a lot in advance!
Bill

答案1

得分: 11

我不明白为什么仅仅计算自年/月的第一天以来有多少个“7天”并不能满足我的需求。

这是我的尝试:

func firstDayOfISOWeek(year int, week int, timezone *time.Location) time.Time {
    date := time.Date(year, 0, 0, 0, 0, 0, 0, timezone)
    isoYear, isoWeek := date.ISOWeek()
    for date.Weekday() != time.Monday { // 迭代回到星期一
        date = date.AddDate(0, 0, -1)
        isoYear, isoWeek = date.ISOWeek()
    }
    for isoYear < year { // 迭代前进到第一周的第一天
        date = date.AddDate(0, 0, 1)
        isoYear, isoWeek = date.ISOWeek()
    }
    for isoWeek < week { // 迭代前进到给定周的第一天
        date = date.AddDate(0, 0, 1)
        isoYear, isoWeek = date.ISOWeek()
    }
    return date
}

这是一个带有健全性检查的可工作示例:http://play.golang.org/p/UVFNFcpaoI

这段代码很容易理解,没有年/月/日的计算,只是简单的迭代。运行时复杂度为O(n),但考虑到n始终小于400,实际上并不是问题。

如果golang的date.AddDate实现正确,它不应该在夏令时、闰年和其他棘手的日期问题上出现问题。

附:有趣的事实 Go – 从 ISO 年周获取一周的第一天的 Unix 时间戳。 2008年第1周的第一天是2007-12-31。这是正确的,你可以在日历中查看。

英文:

I don't see why

> simply counting how many "7 days" there have been since the first day of the year/month doesn't really get me what I need

Here is my attempt:

func firstDayOfISOWeek(year int, week int, timezone *time.Location) time.Time {
	date := time.Date(year, 0, 0, 0, 0, 0, 0, timezone)
	isoYear, isoWeek := date.ISOWeek()
	for date.Weekday() != time.Monday { // iterate back to Monday
		date = date.AddDate(0, 0, -1)
		isoYear, isoWeek = date.ISOWeek()
	}
	for isoYear &lt; year { // iterate forward to the first day of the first week
		date = date.AddDate(0, 0, 1)
		isoYear, isoWeek = date.ISOWeek()
	}
	for isoWeek &lt; week { // iterate forward to the first day of the given week
		date = date.AddDate(0, 0, 1)
		isoYear, isoWeek = date.ISOWeek()
	}
	return date
}

Here is working example with sanity check: http://play.golang.org/p/UVFNFcpaoI

The code is easy to understand, there is no year/month/day arithmetic, just simple iteration. The runtime complexity is O(n), but given that n is always less than 400 - it's actually not a problem at all.

It should not have problems with daylight saving, leap years and other tricky date problems if golang date.AddDate is implemented correctly.

P.S. Funny fact Go – 从 ISO 年周获取一周的第一天的 Unix 时间戳。 First day of week 1 of year 2008 is 2007-12-31. And this is correct, you can check in the calendar.

答案2

得分: 4

我为了这个目的实现了另一个简单的Go包:

https://github.com/snabb/isoweek

示例用法:

st := isoweek.StartTime(1985, 1, time.UTC)
fmt.Println(st)
// 输出:
// 1984-12-31 00:00:00 +0000 UTC

我不喜欢被接受的答案中的方法,因为它来回迭代,这是荒谬的。

我也不喜欢另一个答案中的goweek包,因为它似乎过于复杂,API也很奇怪(为什么要可变参数等)。

英文:

I implemented yet another simple Go package for exactly this purpose:

https://github.com/snabb/isoweek

Example usage:

st := isoweek.StartTime(1985, 1, time.UTC)
fmt.Println(st)
// Output:
// 1984-12-31 00:00:00 +0000 UTC

I did not like the method in the accepted answer because it iterates backwards and forwards which is ridiculous.

I also did not like goweek package in another answer as it seems overly complicated and the API is very strange (why variadic arguments? etc).

答案3

得分: 1

func GetStartDayOfWeek(tm time.Time) time.Time { //获取周一的00:00:00
weekday := time.Duration(tm.Weekday())
if weekday == 0 {
weekday = 7
}
year, month, day := t.Date()
currentZeroDay := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
return currentZeroDay.Add(-1 * (weekday - 1) * 24 * time.Hour)
}

英文:
func GetStartDayOfWeek(tm time.Time) time.Time { //get monday 00:00:00
	weekday := time.Duration(tm.Weekday())
	if weekday == 0 {
		weekday = 7
	}
	year, month, day := t.Date()
	currentZeroDay:= time.Date(year, month, day, 0, 0, 0, 0, time.Local)
	return currentZeroDay.Add(-1 * (weekday - 1) * 24 * time.Hour)
}

答案4

得分: 0

无耻地自我推广一下,我刚刚发布了一个用于在Go中处理周的库:https://github.com/grsmv/goweek

英文:

Shameless self-promotion, but I just released lib for working with weeks in Go: https://github.com/grsmv/goweek

huangapple
  • 本文由 发表于 2013年9月5日 05:33:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/18624177.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定