Golang中如何验证日期

Golang中如何验证日期 我获取到一个字符串格式的出生日期(“12345678”),并通过使用 time.Parse 将该字符串转换为日期。我的函数在这一部分之前工作正常,但如果有人输入了错误的出生日期,它不会给我返回错误。例如:如果我输入 “00000000”,我将不会收到任何错误。请问你能帮我解决这个问题吗?

func (p *Package1) checkBirthdate  {
if len(p.Birthdate) != 0 {
_, err := time.Parse("2006-01-02", p.Birthdate[0:4]+"-"+p.Birthdate[4:6]+"-"+p.Birthdate[6:8])
if err != nil {
fmt. Printf("Error occured %s", p.Birthdate)
}
}

更多关于Golang中如何验证日期的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

Yo_94:

12345678

这个值代表什么日期?你是指像 19700228 这样代表 1970 年 2 月 28 日的形式吗?

更多关于Golang中如何验证日期的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,这应该是其表示形式。 所以,就像如果我输入“00000000”,那么我应该得到一个错误,提示这不是一个有效的日期;或者如果我输入“20200230”,那么我也应该得到一个错误,但我的函数并没有返回这个错误。

我无法复现您描述的行为。请参考以下代码:

package main

import (
	"fmt"
	"time"
)

func parse(s string) (time.Time, error) {
	d, err := time.Parse("2006-01-02", s)
	if err != nil {
		return d, err
	}
	return d, nil
}

func main() {
	d, err := parse("1970-02-28")
	if err != nil {
		panic(err)
	}
	fmt.Println(d)

	d, err = parse("0000-00-00")
	if err != nil {
		panic(err)
	}
	fmt.Println(d)

}

第一次调用 parse 函数返回一个有效日期,而第二次调用则返回一个错误。这一切都符合预期。

参见 https://play.golang.org/p/k8hW04pz6yM

输出:

1970-02-28 00:00:00 +0000 UTC
panic: parsing time "0000-00-00": month out of range

在Go中验证日期时,time.Parse 只会检查日期格式是否有效,但不会验证日期的合理性。例如,"0000-00-00" 在格式上符合 "2006-01-02",因此不会返回错误。要解决这个问题,你需要在解析后添加额外的验证逻辑。以下是一个改进的示例代码:

func (p *Package1) checkBirthdate() error {
    if len(p.Birthdate) == 0 {
        return nil // 或者返回一个错误,取决于你的需求
    }
    
    // 确保字符串长度至少为8位
    if len(p.Birthdate) < 8 {
        return fmt.Errorf("invalid birthdate length: %s", p.Birthdate)
    }
    
    // 解析日期
    birthdateStr := p.Birthdate[0:4] + "-" + p.Birthdate[4:6] + "-" + p.Birthdate[6:8]
    t, err := time.Parse("2006-01-02", birthdateStr)
    if err != nil {
        return fmt.Errorf("failed to parse birthdate %s: %v", p.Birthdate, err)
    }
    
    // 验证日期合理性:年份、月份和日期应在有效范围内
    year := t.Year()
    month := t.Month()
    day := t.Day()
    
    // 检查年份是否合理(例如,出生日期通常在1900年之后)
    if year < 1900 || year > time.Now().Year() {
        return fmt.Errorf("invalid year in birthdate: %s", p.Birthdate)
    }
    
    // 检查月份是否在1到12之间
    if month < 1 || month > 12 {
        return fmt.Errorf("invalid month in birthdate: %s", p.Birthdate)
    }
    
    // 检查日期是否在1到31之间(更精确的检查可以考虑月份和闰年)
    if day < 1 || day > 31 {
        return fmt.Errorf("invalid day in birthdate: %s", p.Birthdate)
    }
    
    // 可选:进一步验证日期是否实际存在(例如,2月30日无效)
    // 这里使用解析后的时间重新格式化为字符串,并与原始输入比较
    formatted := t.Format("2006-01-02")
    expected := fmt.Sprintf("%04d-%02d-%02d", year, month, day)
    if formatted != expected {
        return fmt.Errorf("birthdate does not exist: %s", p.Birthdate)
    }
    
    return nil
}

这段代码首先解析日期,然后检查年份、月份和日期的基本范围。最后,通过比较格式化后的日期与预期字符串,可以捕获像 "0000-00-00""2023-02-30" 这样的无效日期。调用此函数时,如果返回错误,则表示日期无效。

回到顶部