flyfei

时间与日期(time包、时间格式化、定时任务)

1. 语法讲解

Go语言的time包提供了时间的显示和测量功能,日历计算采用公历。

2. 应用场景

3. 编程实例

场景:订单管理系统中的时间处理

package main

import (
    "fmt"
    "time"
)

// 订单结构
type Order struct {
    ID         string
    Customer   string
    Amount     float64
    Status     string
    CreatedAt  time.Time
    UpdatedAt  time.Time
    PaidAt     *time.Time
}

// 创建新订单
func createOrder(id, customer string, amount float64) *Order {
    now := time.Now()
    return &Order{
        ID:        id,
        Customer:  customer,
        Amount:    amount,
        Status:    "created",
        CreatedAt: now,
        UpdatedAt: now,
    }
}

// 标记订单为已支付
func (o *Order) markAsPaid() {
    now := time.Now()
    o.Status = "paid"
    o.PaidAt = &now
    o.UpdatedAt = now
}

// 计算处理时长
func (o *Order) processingDuration() time.Duration {
    endTime := time.Now()
    if o.PaidAt != nil {
        endTime = *o.PaidAt
    }
    return endTime.Sub(o.CreatedAt)
}

// 检查订单是否超时(15分钟未支付)
func (o *Order) isTimeout() bool {
    if o.Status == "paid" {
        return false
    }
    timeout := o.CreatedAt.Add(15 * time.Minute)
    return time.Now().After(timeout)
}

func main() {
    // 创建订单
    order := createOrder("ORD-2023-001", "张三", 299.99)
    fmt.Printf("订单创建时间: %s\n", order.CreatedAt.Format("2006-01-02 15:04:05"))
    
    // 模拟5秒后支付
    time.Sleep(2 * time.Second) // 实际使用中不需要sleep,这里为了演示
    order.markAsPaid()
    
    if order.PaidAt != nil {
        fmt.Printf("订单支付时间: %s\n", order.PaidAt.Format("2006-01-02 15:04:05"))
    }
    
    // 计算处理时长
    duration := order.processingDuration()
    fmt.Printf("订单处理时长: %v\n", duration)
    fmt.Printf("订单处理时长(秒): %.2f秒\n", duration.Seconds())
    
    // 检查超时
    fmt.Printf("订单是否超时: %t\n", order.isTimeout())
    
    // 定时任务:模拟订单状态监控
    fmt.Println("\n启动订单监控...")
    ticker := time.NewTicker(5 * time.Second)
    defer ticker.Stop()
    
    timeoutChan := time.After(25 * time.Second) // 25秒后停止演示

    for {
        select {
        case <-ticker.C:
            // 检查新订单是否超时(模拟)
            newOrder := createOrder(fmt.Sprintf("ORD-%d", time.Now().Unix()), "李四", 199.99)
            
            // 模拟一些订单在超时边缘
            if time.Now().Second()%2 == 0 {
                fmt.Printf("[%s] 新订单 %s 创建, 状态: %s\n", 
                    time.Now().Format("15:04:05"), newOrder.ID, newOrder.Status)
            }
            
        case <-timeoutChan:
            fmt.Println("监控停止")
            break monitor
        }
    }
    
    // 时间计算演示
    now := time.Now()
    fmt.Printf("\n时间计算演示:\n")
    fmt.Printf("当前时间: %s\n", now.Format("2006-01-02 15:04:05"))
    fmt.Printf("一周后: %s\n", now.AddDate(0, 0, 7).Format("2006-01-02"))
    fmt.Printf("3小时前: %s\n", now.Add(-3*time.Hour).Format("15:04:05"))
    fmt.Printf("本月最后一天: %s\n", 
        time.Date(now.Year(), now.Month()+1, 0, 0, 0, 0, 0, now.Location()).Format("2006-01-02"))
}

4. 其他用法

package main

import (
    "fmt"
    "time"
)

func main() {
    // 1. 时间解析和格式化
    timeStr := "2023-08-15 14:30:25"
    layout := "2006-01-02 15:04:05"
    
    parsedTime, err := time.Parse(layout, timeStr)
    if err != nil {
        fmt.Println("时间解析错误:", err)
    } else {
        fmt.Printf("解析的时间: %s\n", parsedTime.Format("2006年01月02日 15点04分"))
    }
    
    // 2. 时区处理
    loc, _ := time.LoadLocation("America/New_York")
    nyTime := time.Now().In(loc)
    fmt.Printf("纽约时间: %s\n", nyTime.Format("2006-01-02 15:04:05 MST"))
    
    // 3. 时间比较
    time1 := time.Now()
    time2 := time1.Add(2 * time.Hour)
    
    fmt.Printf("\n时间比较:\n")
    fmt.Printf("time1 在 time2 之前: %t\n", time1.Before(time2))
    fmt.Printf("time1 在 time2 之后: %t\n", time1.After(time2))
    fmt.Printf("时间相等: %t\n", time1.Equal(time1))
    
    // 4. 时间周期计算
    start := time.Date(2023, 1, 1, 0, 0, 0, 0, time.Local)
    end := time.Date(2023, 12, 31, 23, 59, 59, 0, time.Local)
    
    days := end.Sub(start).Hours() / 24
    fmt.Printf("\n2023年共 %.0f 天\n", days)
    
    // 5. 定时器和超时控制
    fmt.Println("\n启动超时演示...")
    
    // 模拟耗时操作
    done := make(chan bool)
    
    go func() {
        time.Sleep(3 * time.Second) // 模拟工作
        done <- true
    }()
    
    select {
    case <-done:
        fmt.Println("操作完成!")
    case <-time.After(2 * time.Second): // 2秒超时
        fmt.Println("操作超时!")
    }
    
    // 6. 生日计算
    birthday := time.Date(1990, time.October, 5, 0, 0, 0, 0, time.Local)
    age := now.Year() - birthday.Year()
    
    // 如果今年生日还没到,年龄减1
    if now.YearDay() < birthday.YearDay() {
        age--
    }
    
    nextBirthday := time.Date(now.Year(), birthday.Month(), birthday.Day(), 0, 0, 0, 0, time.Local)
    if now.After(nextBirthday) {
        nextBirthday = nextBirthday.AddDate(1, 0, 0)
    }
    daysToBirthday := int(nextBirthday.Sub(now).Hours() / 24)
    
    fmt.Printf("\n年龄: %d岁\n", age)
    fmt.Printf("距离下次生日还有 %d 天\n", daysToBirthday)
}

5. 课时总结