Golang如何根据给定日期精确计算年龄?

Golang如何根据给定日期精确计算年龄? 如何创建一个函数,能够根据给定的出生日期精确计算到今天的年龄?我创建了以下函数,但该函数返回的年龄是错误的。例如:如果我提供 dateOfBirth := 08/15/1990 并尝试计算截至今天的年龄,它会返回 30 而不是 29。有人能帮我解决这个问题吗?

Age = math.Floor(Today.Now().Sub(*dateOfBirth).Hours() / 24 / 365)
4 回复

如果我的生日是明天:(20200909-19820910)/10。

更多关于Golang如何根据给定日期精确计算年龄?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


1990年8月15日是出生日期,今天是2020年9月10日。

9月紧随8月之后,而2020减去1990等于30,30看起来确实是正确的结果。我不确定你为什么期望是29。

除此之外,一天并不总是24小时。它也可能是23或25小时(夏令时),甚至24小时加减1秒(闰秒)。同样,一年也不是365天,大约是365.23天。这就是为什么我们每4年在二月多出一天(每25次跳过,但第4次跳过不跳)……

如何根据给定日期计算截至今天的准确年龄?

我提供了出生日期 dateOfBirth := 08/15/1990,并尝试计算截至今天 [09/09/2020] 的年龄。

Age = math.Floor(Today.Now().Sub(*dateOfBirth).Hours() / 24 / 365)

存在闰年、时区,可能还有夏令时。你的年龄计算公式不正确。


这里是一个正确的年龄计算方法。

package main

import (
	"fmt"
	"time"
)

func age(birthdate, today time.Time) int {
	today = today.In(birthdate.Location())
	ty, tm, td := today.Date()
	today = time.Date(ty, tm, td, 0, 0, 0, 0, time.UTC)
	by, bm, bd := birthdate.Date()
	birthdate = time.Date(by, bm, bd, 0, 0, 0, 0, time.UTC)
	if today.Before(birthdate) {
		return 0
	}
	age := ty - by
	anniversary := birthdate.AddDate(age, 0, 0)
	if anniversary.After(today) {
		age--
	}
	return age
}

func main() {
	layout := "01/02/2006"
	birthdate, _ := time.Parse(layout, "08/15/1990")
	for _, today := range []string{"09/09/2020", "08/15/2020", "08/14/2020", "08/15/1991", "08/14/1991"} {
		today, _ := time.Parse(layout, today)
		fmt.Println(age(birthdate, today), birthdate.Format(layout), today.Format(layout))
	}
}

Go Playground - The Go Programming Language

30 08/15/1990 09/09/2020
30 08/15/1990 08/15/2020
29 08/15/1990 08/14/2020
1 08/15/1990 08/15/1991
0 08/15/1990 08/14/1991

对于出生日期 08/15/1990,第一个生日在 08/15/1991,第十个生日在 08/15/2000,第三十个生日在 08/15/2020。在 09/09/2020 时,age30

根据你提供的代码,问题在于直接使用 Hours()/24/365 进行年龄计算,这种方法没有考虑闰年和月份天数差异,导致精度不足。以下是修正后的解决方案:

package main

import (
    "fmt"
    "time"
)

func CalculateAge(birthDate time.Time) int {
    now := time.Now()
    
    // 计算年份差异
    years := now.Year() - birthDate.Year()
    
    // 如果今年的生日还没到,年龄减1
    if now.YearDay() < birthDate.YearDay() {
        years--
    }
    
    return years
}

func main() {
    // 示例:1990年8月15日出生
    birthDate := time.Date(1990, 8, 15, 0, 0, 0, 0, time.UTC)
    age := CalculateAge(birthDate)
    fmt.Printf("精确年龄: %d岁\n", age)
}

如果需要更精确的年龄(包含月份和天数),可以使用以下扩展版本:

func CalculateExactAge(birthDate time.Time) (years, months, days int) {
    now := time.Now()
    
    // 计算年份
    years = now.Year() - birthDate.Year()
    
    // 计算月份
    months = int(now.Month()) - int(birthDate.Month())
    
    // 计算天数
    days = now.Day() - birthDate.Day()
    
    // 调整负数情况
    if days < 0 {
        // 获取上个月的天数
        lastMonth := now.AddDate(0, -1, 0)
        days += time.Date(lastMonth.Year(), lastMonth.Month()+1, 0, 0, 0, 0, 0, time.UTC).Day()
        months--
    }
    
    if months < 0 {
        months += 12
        years--
    }
    
    return years, months, days
}

func main() {
    birthDate := time.Date(1990, 8, 15, 0, 0, 0, 0, time.UTC)
    years, months, days := CalculateExactAge(birthDate)
    fmt.Printf("精确年龄: %d岁 %d个月 %d天\n", years, months, days)
}

对于你提到的 08/15/1990 格式的字符串输入,可以使用以下解析方式:

func ParseAndCalculateAge(dateStr string) (int, error) {
    birthDate, err := time.Parse("01/02/2006", dateStr)
    if err != nil {
        return 0, err
    }
    return CalculateAge(birthDate), nil
}

func main() {
    age, err := ParseAndCalculateAge("08/15/1990")
    if err != nil {
        fmt.Println("日期解析错误:", err)
        return
    }
    fmt.Printf("年龄: %d岁\n", age)
}

这个解决方案正确处理了闰年和月份天数差异,能够返回精确的年龄计算结果。

回到顶部