I have this so far to count the number of days using http://golang.org/pkg/time/ but I don't know how to exclude weekends and only count business days
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
f := time.Date(2015, time.August, 21, 24, 0, 0, 0, time.UTC)
diff := f.Sub(t)
// convert diff to days
days := int(diff.Hours() / 24)
fmt.Printf("days %d
", days)
}
Here's a simple little solution.
days := 0
for {
if (t.Equal(f)) {
return days
}
if (t.Weekday() != 6 && t.Weekday() != 7) {
days++
}
t.Add(time.Hour*24)
}
You probably don't want to use your original t
variable but keeping the example simple. I loop until t
equals f
, if they're equal I return my days count. If they're not I check to make sure it's a weekday and increment my days count if it is. I unconditionally add one day to my starting time.
Here is a solution thank you evanmcdonnal and luc for answering
package main
import (
"fmt"
"time"
)
func main() {
t := time.Date(2015, time.Now().Month(), time.Now().Day(), time.Now().Hour(), time.Now().Minute(), time.Now().Second(), time.Now().Nanosecond()*0, time.UTC)
fmt.Printf("%s
",t)
f := time.Date(2015, time.August, 22, time.Now().Hour(), time.Now().Minute(), time.Now().Second(), time.Now().Nanosecond()*0, time.UTC)
fmt.Printf("%s
",f)
days :=0
for{
if(t.Equal(f)){
break
}
if(t.Weekday()!=6 && t.Weekday()!=0){
days++
}
t=t.Add(time.Hour*24)
}
fmt.Printf("days %d
", days)
}
output 32
Better to use AddDate
for time calculations greater than 24 hours:
package main
import (
"fmt"
"time"
)
func AddWorkDays(t time.Time, workdays int) time.Time {
curDate := t
for curWorkdays := 0; curWorkdays <= workdays; {
curDate = curDate.AddDate(0, 0, 1)
if curDate.Weekday() != 6 && t.Weekday() != 7 {
curWorkdays++
}
}
return curDate
}
func main() {
now := time.Now()
workdays := 3
t := AddWorkDays(now, workdays)
fmt.Printf(" now %-9v %v
", now.Weekday(), now)
fmt.Printf("later %-9v %v
", t.Weekday(), t)
}
Output on day I'm answering:
now Friday 2017-03-10 21:33:28.395198671 +0000 UTC
later Wednesday 2017-03-15 21:33:28.395198671 +0000 UTC
Realizing that we are calculating an integral and remembering that integrals are usually calculated using primitive functions, which can be taken to be the integral from some fixed time, we can write the following code.
The function primitive()
gives the number of workdays since 3 January 2000, chosen to be a Monday to simplify the formula. The number of workdays between two dates is then given by the difference of primitive()
for the two days.
package main
import (
"fmt"
"time"
)
type Date struct {
year int
month time.Month
day int
}
func date2unix(d Date, loc *time.Location) int64 {
return time.Date(d.year, d.month, d.day, 0, 0, 0, 0, loc).Unix()
}
func primitive(d Date, loc *time.Location) int64 {
// 3 January 2000 was a Monday
base := Date{2000, time.January, 3}
seconds := date2unix(d, loc) - date2unix(base, loc)
weeks := seconds / (7*24*60*60)
seconds_into_week := seconds % (7*24*60*60)
workdays := seconds_into_week / (24*60*60)
if workdays > 5 {
workdays = 5
}
return 5*weeks + workdays
}
func DayCountExcludingWeekends(from, to Date, loc *time.Location) int {
return int(primitive(to, loc) - primitive(from, loc))
}
func main() {
loc, err := time.LoadLocation("Europe/Stockholm")
if err != nil {
panic(err)
}
f := Date{2017, 6, 28}
t := Date{2017, 7, 6}
fmt.Println(DayCountExcludingWeekends(f, t, loc))
}
CalcBusinessDays calculates the business days between two dates, not accounting for the holidays. The calculation is inclusive for both dates.
func CalcBusinessDays(from *time.Time, to *time.Time) int {
totalDays := float32(to.Sub(*from) / (24 * time.Hour))
weekDays := float32(from.Weekday()) - float32(to.Weekday())
businessDays := int(1 + (totalDays*5-weekDays*2)/7)
if to.Weekday() == time.Saturday {
businessDays--
}
if from.Weekday() == time.Sunday {
businessDays--
}
return businessDays
}
I know this has been marked done for a while, but for various reasons I recently had to get the number of weekdays between two dates that could be decades apart.
So if anyone needs it, an O(1) solution.
func GetWeekdaysBetween(start, end time.Time) int {
offset := -int(start.Weekday())
start = start.AddDate(0, 0, -int(start.Weekday()))
offset += int(end.Weekday())
if end.Weekday() == time.Sunday {
offset++
}
end = end.AddDate(0, 0, -int(end.Weekday()))
dif := end.Sub(start).Truncate(time.Hour * 24)
weeks := float64((dif.Hours() / 24) / 7)
return int(math.Round(weeks)*5) + offset
}
If your wanting business days though, this doesn't account for public holidays, which would require some additional planning.