Files
chatlog/pkg/util/time_test.go
Shen Junzheng 78cce92ce3 x
2025-03-19 13:11:09 +08:00

1005 lines
22 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package util
import (
"strings"
"testing"
"time"
)
func TestTimeOf(t *testing.T) {
tests := []struct {
name string
input string
wantTime time.Time
wantOk bool
}{
// 空输入
{
name: "empty string",
input: "",
wantTime: time.Time{},
wantOk: false,
},
{
name: "whitespace only",
input: " ",
wantTime: time.Time{},
wantOk: false,
},
// 自然语言时间
{
name: "now",
input: "now",
wantOk: true, // 不检查具体时间,因为会随运行时间变化
},
{
name: "today",
input: "today",
wantOk: true,
},
{
name: "yesterday",
input: "yesterday",
wantOk: true,
},
{
name: "this-week",
input: "this-week",
wantOk: true,
},
{
name: "last-week",
input: "last-week",
wantOk: true,
},
{
name: "this-month",
input: "this-month",
wantOk: true,
},
{
name: "last-month",
input: "last-month",
wantOk: true,
},
{
name: "this-year",
input: "this-year",
wantOk: true,
},
{
name: "last-year",
input: "last-year",
wantOk: true,
},
{
name: "all",
input: "all",
wantOk: true,
},
// 相对时间
{
name: "1h-ago",
input: "1h-ago",
wantOk: true,
},
{
name: "24h-ago",
input: "24h-ago",
wantOk: true,
},
{
name: "1d-ago",
input: "1d-ago",
wantOk: true,
},
{
name: "7d-ago",
input: "7d-ago",
wantOk: true,
},
{
name: "1w-ago",
input: "1w-ago",
wantOk: true,
},
{
name: "1m-ago",
input: "1m-ago",
wantOk: true,
},
{
name: "1y-ago",
input: "1y-ago",
wantOk: true,
},
{
name: "invalid-ago",
input: "invalid-ago",
wantTime: time.Time{},
wantOk: false,
},
{
name: "0d-ago",
input: "0d-ago",
wantOk: true, // 应该是今天
},
{
name: "-1d-ago",
input: "-1d-ago",
wantTime: time.Time{},
wantOk: false, // 负数应该无效
},
// 季度
{
name: "2020Q1",
input: "2020Q1",
wantTime: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "2020Q2",
input: "2020Q2",
wantTime: time.Date(2020, 4, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "2020Q3",
input: "2020Q3",
wantTime: time.Date(2020, 7, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "2020Q4",
input: "2020Q4",
wantTime: time.Date(2020, 10, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "2020Q5", // 无效季度
input: "2020Q5",
wantTime: time.Time{},
wantOk: false,
},
{
name: "1969Q1", // 早于1970年
input: "1969Q1",
wantTime: time.Time{},
wantOk: false,
},
{
name: "10000Q1", // 超过9999年
input: "10000Q1",
wantTime: time.Time{},
wantOk: false,
},
// 年份
{
name: "2020",
input: "2020",
wantTime: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "1970", // 最早有效年份
input: "1970",
wantTime: time.Date(1970, 1, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "9999", // 最晚有效年份
input: "9999",
wantTime: time.Date(9999, 1, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "1969", // 早于1970年
input: "1969",
wantTime: time.Time{},
wantOk: false,
},
{
name: "10000", // 超过9999年
input: "10000",
wantTime: time.Time{},
wantOk: false,
},
{
name: "202", // 不是4位数字
input: "202",
wantTime: time.Time{},
wantOk: false,
},
// 月份
{
name: "202001",
input: "202001",
wantTime: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "202012",
input: "202012",
wantTime: time.Date(2020, 12, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "2020-01",
input: "2020-01",
wantTime: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "2020-12",
input: "2020-12",
wantTime: time.Date(2020, 12, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "202013", // 无效月份
input: "202013",
wantTime: time.Time{},
wantOk: false,
},
{
name: "2020-13", // 无效月份
input: "2020-13",
wantTime: time.Time{},
wantOk: false,
},
{
name: "2020-00", // 无效月份
input: "2020-00",
wantTime: time.Time{},
wantOk: false,
},
{
name: "196912", // 早于1970年
input: "196912",
wantTime: time.Time{},
wantOk: false,
},
{
name: "1969-12", // 早于1970年
input: "1969-12",
wantTime: time.Time{},
wantOk: false,
},
// 日期格式
{
name: "20200101",
input: "20200101",
wantTime: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "20201231",
input: "20201231",
wantTime: time.Date(2020, 12, 31, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "2020-01-01",
input: "2020-01-01",
wantTime: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "2020-12-31",
input: "2020-12-31",
wantTime: time.Date(2020, 12, 31, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "20200229", // 闰年2月29日
input: "20200229",
wantTime: time.Date(2020, 2, 29, 0, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "20190229", // 非闰年2月29日
input: "20190229",
wantTime: time.Time{},
wantOk: false,
},
{
name: "20200230", // 无效日期
input: "20200230",
wantTime: time.Time{},
wantOk: false,
},
{
name: "2020-02-30", // 无效日期
input: "2020-02-30",
wantTime: time.Time{},
wantOk: false,
},
{
name: "20200000", // 无效日期
input: "20200000",
wantTime: time.Time{},
wantOk: false,
},
{
name: "20200132", // 无效日期
input: "20200132",
wantTime: time.Time{},
wantOk: false,
},
{
name: "19691231", // 早于1970年
input: "19691231",
wantTime: time.Time{},
wantOk: false,
},
{
name: "1969-12-31", // 早于1970年
input: "1969-12-31",
wantTime: time.Time{},
wantOk: false,
},
// 带时间的日期
{
name: "20200101/12:34",
input: "20200101/12:34",
wantTime: time.Date(2020, 1, 1, 12, 34, 0, 0, time.Local),
wantOk: true,
},
{
name: "2020-01-01/12:34",
input: "2020-01-01/12:34",
wantTime: time.Date(2020, 1, 1, 12, 34, 0, 0, time.Local),
wantOk: true,
},
{
name: "20200101/24:00", // 无效时间
input: "20200101/24:00",
wantTime: time.Time{},
wantOk: false,
},
{
name: "20200101/12:60", // 无效时间
input: "20200101/12:60",
wantTime: time.Time{},
wantOk: false,
},
{
name: "20200101/12:34:56", // 不支持的格式
input: "20200101/12:34:56",
wantTime: time.Time{},
wantOk: false,
},
{
name: "20200101/12-34", // 不支持的格式
input: "20200101/12-34",
wantTime: time.Time{},
wantOk: false,
},
{
name: "19691231/12:34", // 早于1970年
input: "19691231/12:34",
wantTime: time.Time{},
wantOk: false,
},
// 完整时间
{
name: "20200101120000",
input: "20200101120000",
wantTime: time.Date(2020, 1, 1, 12, 0, 0, 0, time.Local),
wantOk: true,
},
{
name: "20201231235959",
input: "20201231235959",
wantTime: time.Date(2020, 12, 31, 23, 59, 59, 0, time.Local),
wantOk: true,
},
{
name: "20200101240000", // 无效时间
input: "20200101240000",
wantTime: time.Time{},
wantOk: false,
},
{
name: "20200101126000", // 无效时间
input: "20200101126000",
wantTime: time.Time{},
wantOk: false,
},
{
name: "20200101120060", // 无效时间
input: "20200101120060",
wantTime: time.Time{},
wantOk: false,
},
{
name: "2020010112000", // 长度不对
input: "2020010112000",
wantTime: time.Time{},
wantOk: false,
},
{
name: "202001011200000", // 长度不对
input: "202001011200000",
wantTime: time.Time{},
wantOk: false,
},
{
name: "19691231235959", // 早于1970年
input: "19691231235959",
wantTime: time.Time{},
wantOk: false,
},
// 时间戳(秒)
{
name: "1577836800", // 2020-01-01 00:00:00
input: "1577836800",
wantTime: time.Unix(1577836800, 0),
wantOk: true,
},
{
name: "1609459199", // 2020-12-31 23:59:59
input: "1609459199",
wantTime: time.Unix(1609459199, 0),
wantOk: true,
},
{
name: "999999999", // 小于1000000000
input: "999999999",
wantTime: time.Time{},
wantOk: false,
},
{
name: "253402300800", // 大于253402300799
input: "253402300800",
wantTime: time.Time{},
wantOk: false,
},
{
name: "abc", // 非数字
input: "abc",
wantTime: time.Time{},
wantOk: false,
},
// RFC3339
{
name: "2020-01-01T12:00:00Z",
input: "2020-01-01T12:00:00Z",
wantTime: time.Date(2020, 1, 1, 12, 0, 0, 0, time.UTC),
wantOk: true,
},
{
name: "2020-01-01T12:00:00+08:00",
input: "2020-01-01T12:00:00+08:00",
wantTime: time.Date(2020, 1, 1, 12, 0, 0, 0, time.FixedZone("", 8*60*60)),
wantOk: true,
},
{
name: "2020-01-01T12:00Z",
input: "2020-01-01T12:00Z",
wantTime: time.Date(2020, 1, 1, 12, 0, 0, 0, time.UTC),
wantOk: true,
},
{
name: "2020-01-01T12:00:00", // 缺少时区
input: "2020-01-01T12:00:00",
wantTime: time.Time{},
wantOk: false,
},
{
name: "2020-01-01 12:00:00Z", // 格式不对
input: "2020-01-01 12:00:00Z",
wantTime: time.Time{},
wantOk: false,
},
// 边界情况和特殊情况
{
name: "99999", // 不是有效的时间戳
input: "99999",
wantTime: time.Time{},
wantOk: false,
},
{
name: "2020/01/01", // 不支持的格式
input: "2020/01/01",
wantTime: time.Time{},
wantOk: false,
},
{
name: "01/01/2020", // 不支持的格式
input: "01/01/2020",
wantTime: time.Time{},
wantOk: false,
},
{
name: "2020-1-1", // 不支持的格式
input: "2020-1-1",
wantTime: time.Time{},
wantOk: false,
},
{
name: "20201-01-01", // 不支持的格式
input: "20201-01-01",
wantTime: time.Time{},
wantOk: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotTime, gotOk := TimeOf(tt.input)
if tt.wantOk != gotOk {
t.Errorf("TimeOf() ok = %v, want %v", gotOk, tt.wantOk)
return
}
if !tt.wantOk {
return // 不需要检查时间值
}
if tt.input == "now" || strings.HasSuffix(tt.input, "-ago") ||
tt.input == "today" || tt.input == "yesterday" ||
tt.input == "this-week" || tt.input == "last-week" ||
tt.input == "this-month" || tt.input == "last-month" ||
tt.input == "this-year" || tt.input == "last-year" {
// 对于相对时间,不检查具体值
return
}
if !tt.wantTime.Equal(gotTime) {
t.Errorf("TimeOf() = %v, want %v", gotTime, tt.wantTime)
}
})
}
}
func TestTimeRangeOf(t *testing.T) {
tests := []struct {
name string
input string
wantStart time.Time
wantEnd time.Time
wantOk bool
}{
// 空输入
{
name: "empty string",
input: "",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
{
name: "whitespace only",
input: " ",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
// all 特殊情况
{
name: "all",
input: "all",
wantStart: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
wantEnd: time.Date(9999, 12, 31, 23, 59, 59, 999999999, time.UTC),
wantOk: true,
},
{
name: "ALL (uppercase)",
input: "ALL",
wantStart: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC),
wantEnd: time.Date(9999, 12, 31, 23, 59, 59, 999999999, time.UTC),
wantOk: true,
},
// 相对时间范围
{
name: "last-1d",
input: "last-1d",
wantOk: true, // 不检查具体时间,因为会随运行时间变化
},
{
name: "last-7d",
input: "last-7d",
wantOk: true,
},
{
name: "last-30d",
input: "last-30d",
wantOk: true,
},
{
name: "last-1w",
input: "last-1w",
wantOk: true,
},
{
name: "last-4w",
input: "last-4w",
wantOk: true,
},
{
name: "last-1m",
input: "last-1m",
wantOk: true,
},
{
name: "last-3m",
input: "last-3m",
wantOk: true,
},
{
name: "last-1y",
input: "last-1y",
wantOk: true,
},
{
name: "last-0d", // 无效输入
input: "last-0d",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
{
name: "last--1d", // 无效输入
input: "last--1d",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
{
name: "last-1x", // 无效输入
input: "last-1x",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
// 时间区间
{
name: "2020-01-01~2020-01-31",
input: "2020-01-01~2020-01-31",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "2020-01-01,2020-01-31",
input: "2020-01-01,2020-01-31",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "2020-01-01 to 2020-01-31",
input: "2020-01-01 to 2020-01-31",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "20200101~20200131",
input: "20200101~20200131",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "2020-01-31~2020-01-01", // 开始时间晚于结束时间
input: "2020-01-31~2020-01-01",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.Local),
wantOk: true, // 应该自动交换
},
{
name: "2020-01-01~invalid", // 结束时间无效
input: "2020-01-01~invalid",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
{
name: "invalid~2020-01-31", // 开始时间无效
input: "invalid~2020-01-31",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
{
name: "2020-01-01~2020-02-30", // 结束时间无效日期
input: "2020-01-01~2020-02-30",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
{
name: "2020-01-01~", // 缺少结束时间
input: "2020-01-01~",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
{
name: "~2020-01-31", // 缺少开始时间
input: "~2020-01-31",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
// 单个时间点,根据粒度确定范围
{
name: "2020-01-01", // 精确到天
input: "2020-01-01",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 1, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "20200101", // 精确到天
input: "20200101",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 1, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "2020-01", // 精确到月
input: "2020-01",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "202001", // 精确到月
input: "202001",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "2020Q1", // 精确到季度
input: "2020Q1",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 3, 31, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "2020", // 精确到年
input: "2020",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 12, 31, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "2020-01-01/12:34", // 精确到分钟
input: "2020-01-01/12:34",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 1, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "20200101120000", // 精确到秒
input: "20200101120000",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 1, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "1577836800", // 时间戳 2020-01-01 00:00:00
input: "1577836800",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 1, 1, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "2020-01-01T12:00:00Z", // RFC3339
input: "2020-01-01T12:00:00Z",
wantStart: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
wantEnd: time.Date(2020, 1, 1, 23, 59, 59, 999999999, time.UTC),
wantOk: true,
},
// 自然语言时间
{
name: "today",
input: "today",
wantOk: true,
},
{
name: "yesterday",
input: "yesterday",
wantOk: true,
},
{
name: "this-week",
input: "this-week",
wantOk: true,
},
{
name: "last-week",
input: "last-week",
wantOk: true,
},
{
name: "this-month",
input: "this-month",
wantOk: true,
},
{
name: "last-month",
input: "last-month",
wantOk: true,
},
{
name: "this-year",
input: "this-year",
wantOk: true,
},
{
name: "last-year",
input: "last-year",
wantOk: true,
},
// 边界情况和特殊情况
{
name: "invalid", // 无效输入
input: "invalid",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
{
name: "2020-02-29", // 闰年2月29日
input: "2020-02-29",
wantStart: time.Date(2020, 2, 29, 0, 0, 0, 0, time.Local),
wantEnd: time.Date(2020, 2, 29, 23, 59, 59, 999999999, time.Local),
wantOk: true,
},
{
name: "2019-02-29", // 非闰年2月29日
input: "2019-02-29",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
{
name: "2020-04-31", // 无效日期
input: "2020-04-31",
wantStart: time.Time{},
wantEnd: time.Time{},
wantOk: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotStart, gotEnd, gotOk := TimeRangeOf(tt.input)
if tt.wantOk != gotOk {
t.Errorf("TimeRangeOf() ok = %v, want %v", gotOk, tt.wantOk)
return
}
if !tt.wantOk {
return // 不需要检查时间值
}
if tt.input == "today" || tt.input == "yesterday" ||
tt.input == "this-week" || tt.input == "last-week" ||
tt.input == "this-month" || tt.input == "last-month" ||
tt.input == "this-year" || tt.input == "last-year" ||
strings.HasPrefix(tt.input, "last-") {
// 对于相对时间,不检查具体值
return
}
if !tt.wantStart.Equal(gotStart) {
t.Errorf("TimeRangeOf() start = %v, want %v", gotStart, tt.wantStart)
}
if !tt.wantEnd.Equal(gotEnd) {
t.Errorf("TimeRangeOf() end = %v, want %v", gotEnd, tt.wantEnd)
}
})
}
}
// 测试边界情况
func TestTimeOfEdgeCases(t *testing.T) {
// 测试非常长的数字字符串
longDigits := "99999999999999999999999999999999999999"
_, ok := TimeOf(longDigits)
if ok {
t.Errorf("TimeOf(%s) should return false for very long digit string", longDigits)
}
// 测试非常长的字符串
longString := strings.Repeat("a", 10000)
_, ok = TimeOf(longString)
if ok {
t.Errorf("TimeOf(%s) should return false for very long string", "very_long_string")
}
// 测试特殊字符
specialChars := "!@#$%^&*()"
_, ok = TimeOf(specialChars)
if ok {
t.Errorf("TimeOf(%s) should return false for special characters", specialChars)
}
// 测试SQL注入类字符串
sqlInjection := "2020-01-01' OR '1'='1"
_, ok = TimeOf(sqlInjection)
if ok {
t.Errorf("TimeOf(%s) should return false for SQL injection attempt", sqlInjection)
}
}
// 测试时区处理
func TestTimeOfTimezones(t *testing.T) {
// RFC3339格式的时区处理
utcTime, ok := TimeOf("2020-01-01T12:00:00Z")
if !ok {
t.Fatalf("TimeOf(2020-01-01T12:00:00Z) failed")
}
estTime, ok := TimeOf("2020-01-01T12:00:00-05:00")
if !ok {
t.Fatalf("TimeOf(2020-01-01T12:00:00-05:00) failed")
}
// UTC比EST时区快5小时所以相同时钟时间的UTC应该比EST早5小时
// 转换为UTC后比较
utcInUTC := utcTime.UTC()
estInUTC := estTime.UTC()
// EST时区是-5小时所以相同时钟时间的EST转为UTC后应该比UTC的时钟时间多5小时
hourDiff := estInUTC.Hour() - utcInUTC.Hour()
if hourDiff != 5 {
t.Errorf("Expected 5 hour difference between UTC and EST, got %v", hourDiff)
}
}
// 测试闰年处理
func TestLeapYearHandling(t *testing.T) {
// 测试闰年2月29日
leapDay, ok := TimeOf("20200229")
if !ok {
t.Fatalf("TimeOf(20200229) failed for leap year")
}
if leapDay.Day() != 29 || leapDay.Month() != 2 || leapDay.Year() != 2020 {
t.Errorf("Expected 2020-02-29, got %v", leapDay)
}
// 测试非闰年2月29日
_, ok = TimeOf("20190229")
if ok {
t.Errorf("TimeOf(20190229) should fail for non-leap year")
}
// 测试世纪闰年规则 (2000是闰年2100不是)
_, ok = TimeOf("20000229")
if !ok {
t.Errorf("TimeOf(20000229) should succeed for century leap year")
}
_, ok = TimeOf("21000229")
if ok {
t.Errorf("TimeOf(21000229) should fail for non-leap century year")
}
}