Question

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

Was it helpful?

Solution

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 < year { // iterate forward to the first day of the first week
        date = date.AddDate(0, 0, 1)
        isoYear, isoWeek = date.ISOWeek()
    }
    for isoWeek < 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 :) First day of week 1 of year 2008 is 2007-12-31. And this is correct, you can check in the calendar.

OTHER TIPS

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).

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)
}

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top