1 介绍

1.1 定义

01.Carbon简介
    a.功能说明
        Carbon是Golang生态中最流行的时间日期处理库,对标PHP中的Carbon和JavaScript中的Moment.js。它基于time.Time进行封装,提供了更简洁直观的API来处理日期时间相关操作。Carbon通过链式调用和丰富的格式化选项,大大简化了时间计算、格式转换、时区处理等常见任务。该库支持农历转换、生肖星座计算等中国特色功能,是处理时间日期的首选工具。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 创建Carbon实例
            now := carbon.Now()
            fmt.Println("当前时间:", now.ToString())

            // 时间运算示例
            tomorrow := now.AddDay()
            fmt.Println("明天:", tomorrow.ToDateString())

            // 格式化输出
            fmt.Println("标准格式:", now.ToDateTimeString())
            fmt.Println("自定义格式:", now.Format("Y年m月d日 H:i:s"))

            // 时间比较
            if now.Lt(tomorrow) {
                fmt.Println("现在早于明天")
            }

            // 解析时间字符串
            parsed := carbon.Parse("2024-01-15 14:30:00")
            fmt.Println("解析的时间:", parsed.ToDateTimeString())

            // 时区处理
            tokyo := now.SetTimezone(carbon.Tokyo)
            fmt.Println("东京时间:", tokyo.ToDateTimeString())
        }
        ---

1.2 核心概念

01.Carbon实例
    a.不可变性
        Carbon采用不可变设计模式,每次操作都返回新的Carbon实例而不修改原实例。这种设计避免了副作用,使代码更安全可预测。例如AddDay()不会修改原时间对象,而是返回新的Carbon实例表示明天的时间。这与time.Time的可变性形成对比,大大降低了并发场景下的数据竞争风险。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 不可变性演示
            original := carbon.Parse("2024-01-15 10:00:00")
            fmt.Println("原始时间:", original.ToDateTimeString())

            // 执行加法操作
            modified := original.AddHours(5)
            fmt.Println("修改后:", modified.ToDateTimeString())
            fmt.Println("原始未变:", original.ToDateTimeString()) // 原实例不受影响

            // 链式调用
            result := carbon.Now().
                AddDays(7).
                StartOfDay().
                AddHours(9)
            fmt.Println("链式结果:", result.ToDateTimeString())

            // 多次使用原实例
            tomorrow := original.AddDay()
            nextWeek := original.AddWeek()
            fmt.Println("明天:", tomorrow.ToDateString())
            fmt.Println("下周:", nextWeek.ToDateString())
        }
        ---

02.时区感知
    a.功能说明
        Carbon内置全球时区支持,可以轻松在不同时区之间转换。每个Carbon实例都关联一个时区,默认使用系统时区。通过SetTimezone()可以切换时区,时间值会自动调整。Carbon预定义了常用时区常量如carbon.Tokyo、carbon.London等,也支持IANA时区数据库标准名称如"Asia/Shanghai"。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 获取当前时间(系统时区)
            local := carbon.Now()
            fmt.Println("本地时间:", local.ToString())

            // 转换到不同时区
            tokyo := local.SetTimezone(carbon.Tokyo)
            london := local.SetTimezone(carbon.London)
            ny := local.SetTimezone(carbon.NewYork)

            fmt.Println("东京时间:", tokyo.ToDateTimeString())
            fmt.Println("伦敦时间:", london.ToDateTimeString())
            fmt.Println("纽约时间:", ny.ToDateTimeString())

            // 使用IANA时区名称
            shanghai := local.SetTimezone("Asia/Shanghai")
            fmt.Println("上海时间:", shanghai.ToDateTimeString())

            // 创建时指定时区
            specificTime := carbon.Parse("2024-01-15 14:00:00", carbon.PRC)
            fmt.Println("指定时区:", specificTime.ToString())
        }
        ---

03.语言本地化
    a.功能说明
        Carbon支持多语言本地化,可以将月份、星期等输出为不同语言。内置支持中文、英文、日文等数十种语言。通过SetLanguage()设置语言后,ToMonthString()、ToDayOfWeekString()等方法会自动使用对应语言。这对于国际化应用非常有用,无需手动维护翻译映射表。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 英语输出
            now.SetLanguage("en")
            fmt.Println("English Month:", now.ToMonthString())
            fmt.Println("English Day:", now.ToDayOfWeekString())

            // 中文输出
            now.SetLanguage("zh-CN")
            fmt.Println("中文月份:", now.ToMonthString())
            fmt.Println("中文星期:", now.ToDayOfWeekString())

            // 日语输出
            now.SetLanguage("ja")
            fmt.Println("日本語月:", now.ToMonthString())
            fmt.Println("日本語曜日:", now.ToDayOfWeekString())

            // 在格式化中使用本地化
            now.SetLanguage("zh-CN")
            fmt.Println("完整日期:", now.ToFormattedDateString())
            fmt.Println("相对时间:", now.DiffForHumans())
        }
        ---

1.3 优缺点

01.核心优势
    a.API简洁性
        Carbon相比标准库time包提供了更直观的API。例如时间加减,time包需要使用time.Add(24*time.Hour),而Carbon只需AddDay()。格式化时间,time包使用晦涩的"2006-01-02 15:04:05"魔法数字,Carbon则使用PHP风格的"Y-m-d H:i:s"更易记忆。链式调用支持使代码更流畅,一行代码即可完成复杂的时间计算。
    b.代码对比
        ---
        package main

        import (
            "fmt"
            "time"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 标准库方式(复杂)
            now := time.Now()
            tomorrow := now.Add(24 * time.Hour)
            formatted := tomorrow.Format("2006-01-02 15:04:05")
            fmt.Println("标准库:", formatted)

            // Carbon方式(简洁)
            carbonResult := carbon.Now().AddDay().ToDateTimeString()
            fmt.Println("Carbon:", carbonResult)

            // 复杂计算对比
            // 标准库:下周一早上9点
            std := time.Now()
            daysUntilMonday := (8 - int(std.Weekday())) % 7
            if daysUntilMonday == 0 {
                daysUntilMonday = 7
            }
            nextMonday := std.Add(time.Duration(daysUntilMonday) * 24 * time.Hour)
            result := time.Date(nextMonday.Year(), nextMonday.Month(), nextMonday.Day(),
                9, 0, 0, 0, nextMonday.Location())
            fmt.Println("标准库下周一:", result.Format("2006-01-02 15:04:05"))

            // Carbon:同样的需求
            carbonMonday := carbon.Now().Next(carbon.Monday).StartOfDay().AddHours(9)
            fmt.Println("Carbon下周一:", carbonMonday.ToDateTimeString())
        }
        ---

    c.丰富功能
        Carbon提供了大量开箱即用的功能,包括时间差值计算、相对时间显示、时间范围判断、农历转换、生肖星座等。这些功能在标准库中需要手动实现,而Carbon直接提供了经过充分测试的实现。特别是中国特色功能如农历支持,填补了Golang生态的空白。
    d.功能演示
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 相对时间(人性化显示)
            past := carbon.Now().SubDays(3)
            fmt.Println("相对时间:", past.DiffForHumans()) // "3天前"

            // 时间范围判断
            start := carbon.Parse("2024-01-01")
            end := carbon.Parse("2024-12-31")
            if now.Between(start, end) {
                fmt.Println("在2024年范围内")
            }

            // 农历转换
            lunar := now.Lunar()
            fmt.Printf("农历: %d年%s%d月%d日\n",
                lunar.Year(), lunar.LeapMonth(), lunar.Month(), lunar.Day())

            // 生肖星座
            fmt.Println("生肖:", now.Animal())
            fmt.Println("星座:", now.Constellation())

            // 工作日判断
            if now.IsWeekday() {
                fmt.Println("今天是工作日")
            }

            // 季节判断
            fmt.Println("季节:", now.Season())
        }
        ---

02.潜在限制
    a.性能开销
        Carbon对time.Time进行了封装,引入了轻微的性能开销。每次操作创建新实例会增加内存分配。对于高频时间操作(如每秒数百万次),可能产生可感知的性能影响。但对于绝大多数应用,这点开销相比开发效率提升是值得的。性能敏感场景建议��准测试后决定。
    b.性能对比
        ---
        package main

        import (
            "fmt"
            "time"
            "testing"
            "github.com/golang-module/carbon/v2"
        )

        // 标准库基准测试
        func BenchmarkStdLib(b *testing.B) {
            for i := 0; i < b.N; i++ {
                now := time.Now()
                _ = now.Add(24 * time.Hour)
            }
        }

        // Carbon基准测试
        func BenchmarkCarbon(b *testing.B) {
            for i := 0; i < b.N; i++ {
                now := carbon.Now()
                _ = now.AddDay()
            }
        }

        func main() {
            // 性能测试示例
            start := time.Now()
            for i := 0; i < 1000000; i++ {
                _ = time.Now().Add(24 * time.Hour)
            }
            stdDuration := time.Since(start)

            start = time.Now()
            for i := 0; i < 1000000; i++ {
                _ = carbon.Now().AddDay()
            }
            carbonDuration := time.Since(start)

            fmt.Printf("标准库耗时: %v\n", stdDuration)
            fmt.Printf("Carbon耗时: %v\n", carbonDuration)
            fmt.Printf("性能比: %.2f%%\n", float64(carbonDuration)/float64(stdDuration)*100)
        }
        ---

    c.学习曲线
        虽然Carbon API简洁,但需要学习新的方法名和格式化语法。团队成员需要熟悉Carbon特有的概念如不可变性、链式调用等。对于只做简单时间操作的项目,引入额外依赖可能过度设计。建议根据项目复杂度和团队技术栈选择,避免为了使用而使用。

1.4 使用场景

01.Web应用开发
    a.场景说明
        Web应用中大量涉及时间处理,如用户注册时间、文章发布时间、评论时间戳等。Carbon简化了时间格式化、时区转换、相对时间显示等常见需求。例如显示"3小时前"、将UTC时间转为用户本地时区、计算会员到期剩余天数等。与ORM配合使用时,可以优雅地处理created_at、updated_at字段。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // 用户模型
        type User struct {
            ID        int
            Username  string
            CreatedAt carbon.Carbon
            LastLogin carbon.Carbon
        }

        func main() {
            user := User{
                ID:        1,
                Username:  "alice",
                CreatedAt: carbon.Parse("2023-01-15 10:30:00"),
                LastLogin: carbon.Now().SubHours(3),
            }

            // 显示注册时间(相对时间)
            fmt.Printf("注册于: %s\n", user.CreatedAt.DiffForHumans())

            // 显示最后登录(人性化)
            fmt.Printf("最后登录: %s\n", user.LastLogin.DiffForHumans())

            // 计算账号年龄
            age := user.CreatedAt.DiffInYears(carbon.Now())
            fmt.Printf("账号年龄: %d年\n", age)

            // 时区转换(假设用户在东京)
            userLocalTime := user.LastLogin.SetTimezone(carbon.Tokyo)
            fmt.Printf("用户本地时间: %s\n", userLocalTime.ToDateTimeString())

            // 判断是否新用户(注册不超过7天)
            if user.CreatedAt.Gt(carbon.Now().SubDays(7)) {
                fmt.Println("新用户标识")
            }
        }
        ---

02.日志系统
    a.场景说明
        日志系统需要统一的时间格式和精确的时间戳。Carbon可以轻松实现日志时间的标准化、不同格式的时间解析、日志文件按日期归档等功能。支持毫秒级时间戳、UTC时间存储、本地时区显示等需求。特别适合分布式系统中统一时间处理逻辑。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "os"
            "github.com/golang-module/carbon/v2"
        )

        // 日志记录器
        type Logger struct {
            file *os.File
        }

        func (l *Logger) Log(level, message string) {
            now := carbon.Now(carbon.UTC)

            // 毫秒级时间戳
            timestamp := now.ToTimestampWithMillisecond()

            // 标准格式
            formatted := now.ToDateTimeString()

            // ISO8601格式
            iso := now.ToRfc3339String()

            logEntry := fmt.Sprintf("[%s] [%s] %s (timestamp: %d)\n",
                formatted, level, message, timestamp)

            fmt.Print(logEntry)
            // l.file.WriteString(logEntry) // 实际写入文件
        }

        func main() {
            logger := &Logger{}

            // 记录不同级别日志
            logger.Log("INFO", "应用启动")
            logger.Log("WARN", "连接池达到80%")
            logger.Log("ERROR", "数据库查询失败")

            // 日志文件命名(按日期)
            filename := carbon.Now().ToShortDateString() + ".log"
            fmt.Printf("日志文件: %s\n", filename)

            // 解析不同格式的日志时间
            logs := []string{
                "2024-01-15 10:30:45",
                "2024/01/15 14:20:30",
                "15-Jan-2024 16:45:00",
            }

            for _, log := range logs {
                parsed := carbon.Parse(log)
                if !parsed.IsZero() {
                    fmt.Printf("解析成功: %s -> %s\n",
                        log, parsed.ToDateTimeString())
                }
            }
        }
        ---

03.任务调度
    a.场景说明
        定时任务、cron作业、延迟队列等场景需要精确的时间计算。Carbon可以计算下次执行时间、判断是否到达触发时刻、处理时区差异等。支持复杂的时间规则如"每周一早上9点"、"每月最后一天"、"工作日每2小时"等。与调度器配合使用可以构建强大的任务系统。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "time"
            "github.com/golang-module/carbon/v2"
        )

        // 定时任务
        type Task struct {
            Name     string
            Schedule string
            NextRun  carbon.Carbon
        }

        func (t *Task) CalculateNextRun() {
            now := carbon.Now()

            switch t.Schedule {
            case "daily":
                // 每天凌晨执行
                t.NextRun = now.AddDay().StartOfDay()

            case "weekly":
                // 每周一早上9点
                t.NextRun = now.Next(carbon.Monday).StartOfDay().AddHours(9)

            case "monthly":
                // 每月1号中午12点
                t.NextRun = now.AddMonth().StartOfMonth().StartOfDay().AddHours(12)

            case "hourly":
                // 每小时整点
                t.NextRun = now.AddHour().StartOfHour()
            }
        }

        func (t *Task) ShouldRun() bool {
            return carbon.Now().Gte(t.NextRun)
        }

        func main() {
            tasks := []Task{
                {Name: "数据备份", Schedule: "daily"},
                {Name: "周报生成", Schedule: "weekly"},
                {Name: "账单结算", Schedule: "monthly"},
                {Name: "健康检查", Schedule: "hourly"},
            }

            // 计算所有任务的下次执行时间
            for i := range tasks {
                tasks[i].CalculateNextRun()
                fmt.Printf("任务: %s, 下次执行: %s (%s)\n",
                    tasks[i].Name,
                    tasks[i].NextRun.ToDateTimeString(),
                    tasks[i].NextRun.DiffForHumans())
            }

            // 模拟任务调度器
            fmt.Println("\n开始任务调度...")
            for _, task := range tasks {
                if task.ShouldRun() {
                    fmt.Printf("执行任务: %s\n", task.Name)
                } else {
                    remaining := carbon.Now().DiffInSeconds(task.NextRun)
                    fmt.Printf("任务 %s 还需等待 %d 秒\n", task.Name, remaining)
                }
            }
        }
        ---

04.数据分析
    a.场景说明
        数据分析中常需要按时间维度聚合统计,如日活、周活、月度报表等。Carbon可以轻松获取时间范围的开始和结束、遍历时间序列、计算时间跨度等。支持各种时间粒度的分组,如按小时、按天、按周、按月统计。与数据库查询结合可以高效生成时间维度报表。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // 数据点
        type DataPoint struct {
            Timestamp carbon.Carbon
            Value     float64
        }

        func main() {
            // 生成本周每天的时间范围
            fmt.Println("本周日期范围:")
            startOfWeek := carbon.Now().StartOfWeek()
            endOfWeek := carbon.Now().EndOfWeek()

            current := startOfWeek
            for current.Lte(endOfWeek) {
                fmt.Printf("  %s (%s)\n",
                    current.ToShortDateString(),
                    current.ToShortDayOfWeekString())
                current = current.AddDay()
            }

            // 生成过去7天的日期列表(用于查询)
            fmt.Println("\n过去7天:")
            dates := make([]string, 0, 7)
            for i := 6; i >= 0; i-- {
                date := carbon.Now().SubDays(i)
                dates = append(dates, date.ToShortDateString())
                fmt.Printf("  %s\n", date.ToShortDateString())
            }

            // 本月每周的统计范围
            fmt.Println("\n本月周范围:")
            monthStart := carbon.Now().StartOfMonth()
            monthEnd := carbon.Now().EndOfMonth()

            weekStart := monthStart.StartOfWeek()
            weekNum := 1
            for weekStart.Lt(monthEnd) {
                weekEnd := weekStart.EndOfWeek()
                if weekEnd.Gt(monthEnd) {
                    weekEnd = monthEnd
                }
                fmt.Printf("  第%d周: %s 至 %s\n",
                    weekNum,
                    weekStart.ToShortDateString(),
                    weekEnd.ToShortDateString())
                weekStart = weekStart.AddWeek()
                weekNum++
            }

            // 按时间段聚合数据
            fmt.Println("\n时间段分组:")
            now := carbon.Now()
            periods := map[string]carbon.Carbon{
                "今日":  now.StartOfDay(),
                "本周":  now.StartOfWeek(),
                "本月":  now.StartOfMonth(),
                "本季":  now.StartOfQuarter(),
                "今年":  now.StartOfYear(),
            }

            for name, start := range periods {
                days := start.DiffInDays(now)
                fmt.Printf("  %s: %s (已过%d天)\n",
                    name,
                    start.ToShortDateString(),
                    days)
            }
        }
        ---

1.5 设计理念

01.流畅接口
    a.设计思想
        Carbon采用流畅接口(Fluent Interface)设计模式,所有方法都返回Carbon实例本身或新的Carbon实例,支持链式调用。这种设计使代码读起来像自然语言,大大提高了代码的可读性和表达力。例如Now().AddDays(7).StartOfDay()清晰表达了"从现在开始,加7天后,取那天的开始时刻"。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 链式调用示例
            result := carbon.Now().
                AddMonths(3).          // 3个月后
                EndOfMonth().          // 该月的最后时刻
                StartOfDay().          // 当天的开始
                AddHours(9).           // 加9小时
                AddMinutes(30)         // 加30分钟

            fmt.Println("计算结果:", result.ToDateTimeString())

            // 复杂的时间计算
            deadline := carbon.Parse("2024-12-31 23:59:59").
                SubMonths(1).          // 往前推1个月
                StartOfMonth().        // 月初
                Next(carbon.Monday).   // 下个周一
                AddWeeks(2).           // 再加2周
                SetHour(18).           // 设置为18点
                SetMinute(0).          // 分钟归零
                SetSecond(0)           // 秒钟归零

            fmt.Println("截止日期:", deadline.ToDateTimeString())

            // 条件链式调用
            t := carbon.Now()
            if t.IsWeekend() {
                t = t.Next(carbon.Monday) // 如果是周末,取下周一
            }
            t = t.StartOfDay().AddHours(9)
            fmt.Println("下个工作日早上9点:", t.ToDateTimeString())

            // 多步骤格式化
            formatted := carbon.Parse("2024-01-15 14:30:45").
                SetTimezone(carbon.Shanghai).
                SetLanguage("zh-CN").
                ToDateTimeString()
            fmt.Println("格式化结果:", formatted)
        }
        ---

02.语义化命名
    a.命名哲学
        Carbon的方法命名遵循语义化原则,方法名直接表达功能意图。例如IsWeekday()、IsLeapYear()、IsToday()等布尔方法,ToDateString()、ToTimeString()等转换方法,AddDay()、SubWeek()等运算方法。这种命名避免了查文档的频率,提高了开发效率和代码自解释性。
    b.代码演示
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 判断方法(Is系列)
            fmt.Println("是否周末:", now.IsWeekend())
            fmt.Println("是否闰年:", now.IsLeapYear())
            fmt.Println("是否今天:", now.IsToday())
            fmt.Println("是否过去:", now.IsPast())
            fmt.Println("是否未来:", now.IsFuture())
            fmt.Println("是否工作日:", now.IsWeekday())

            // 转换方法(To系列)
            fmt.Println("转日期:", now.ToDateString())
            fmt.Println("转时间:", now.ToTimeString())
            fmt.Println("转日期时间:", now.ToDateTimeString())
            fmt.Println("转时间戳:", now.ToTimestamp())
            fmt.Println("转RFC3339:", now.ToRfc3339String())

            // 运算方法(Add/Sub系列)
            fmt.Println("加1天:", now.AddDay().ToDateString())
            fmt.Println("减1周:", now.SubWeek().ToDateString())
            fmt.Println("加3月:", now.AddMonths(3).ToDateString())
            fmt.Println("减2年:", now.SubYears(2).ToDateString())

            // 范围方法(Start/End系列)
            fmt.Println("日开始:", now.StartOfDay().ToDateTimeString())
            fmt.Println("日结束:", now.EndOfDay().ToDateTimeString())
            fmt.Println("周开始:", now.StartOfWeek().ToDateTimeString())
            fmt.Println("月结束:", now.EndOfMonth().ToDateTimeString())

            // 比较方法(Eq/Gt/Lt系列)
            tomorrow := now.AddDay()
            fmt.Println("等于:", now.Eq(now))
            fmt.Println("大于:", tomorrow.Gt(now))
            fmt.Println("小于:", now.Lt(tomorrow))
            fmt.Println("介于:", now.Between(now.SubDay(), tomorrow))
        }
        ---

03.零值安全
    a.安全设计
        Carbon对零值和无效值进行了特殊处理,避免panic。当解析失败或遇到无效操作时,返回零值Carbon实例而非nil,可以通过IsZero()判断。这种设计符合Golang的错误处理哲学,让代码更健壮。所有方法都能安全地在零值上调用,不会引发运行时恐慌。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 解析无效时间字符串
            invalid := carbon.Parse("invalid-date")
            fmt.Println("是否零值:", invalid.IsZero())
            fmt.Println("零值输出:", invalid.ToDateTimeString()) // 安全返回空字符串

            // 零值上的安全操作
            var zero carbon.Carbon
            fmt.Println("零值IsZero:", zero.IsZero())
            result := zero.AddDay() // 不会panic
            fmt.Println("零值运算:", result.IsZero())

            // 错误处理模式
            dateStr := "2024-13-45" // 无效日期
            parsed := carbon.Parse(dateStr)
            if parsed.IsZero() {
                fmt.Printf("解析失败: %s\n", dateStr)
                // 使用默认值
                parsed = carbon.Now()
            }
            fmt.Println("最终时间:", parsed.ToDateTimeString())

            // 安全的时区设置
            t := carbon.Parse("2024-01-15 10:00:00")
            withTimezone := t.SetTimezone("Invalid/Timezone")
            if withTimezone.Error != nil {
                fmt.Println("时区错误:", withTimezone.Error)
                // 继续使用原时间
                withTimezone = t
            }

            // 安全的格式化
            formatted := carbon.Parse("").ToDateTimeString()
            if formatted == "" {
                fmt.Println("空时间的格式化结果为空字符串")
            }

            // 批量解析时的错误处理
            dates := []string{
                "2024-01-15",
                "invalid",
                "2024-02-20",
                "2024-99-99",
            }

            validDates := make([]carbon.Carbon, 0)
            for _, dateStr := range dates {
                c := carbon.Parse(dateStr)
                if !c.IsZero() {
                    validDates = append(validDates, c)
                } else {
                    fmt.Printf("跳过无效日期: %s\n", dateStr)
                }
            }

            fmt.Printf("有效日期数量: %d\n", len(validDates))
        }
        ---

04.性能优先
    a.优化策略
        虽然Carbon进行了封装,但在关键路径上进行了性能优化。内部缓存了time.Time对象,避免重复转换。时区和语言对象采用单例模式,减少内存占用。提供了批量操作方法减少函数调用开销。对于性能敏感场景,可以使用ToStdTime()转回标准库进行底层操作。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "time"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // Carbon与标准库互转
            now := carbon.Now()
            stdTime := now.ToStdTime() // 转为time.Time
            fmt.Println("标准库时间:", stdTime)

            backToCarbon := carbon.CreateFromStdTime(stdTime)
            fmt.Println("转回Carbon:", backToCarbon.ToDateTimeString())

            // 批量时间生成(复用Carbon实例)
            base := carbon.Parse("2024-01-01")
            dates := make([]carbon.Carbon, 0, 365)
            current := base
            for i := 0; i < 365; i++ {
                dates = append(dates, current)
                current = current.AddDay()
            }
            fmt.Printf("生成了%d个日期\n", len(dates))

            // 性能关键代码使用标准库
            start := time.Now()
            for i := 0; i < 1000000; i++ {
                _ = time.Now().Add(time.Hour)
            }
            stdDuration := time.Since(start)

            // 非性能关键用Carbon提高可读性
            tasks := []struct {
                Name string
                Due  carbon.Carbon
            }{
                {"任务1", carbon.Now().AddDays(7)},
                {"任务2", carbon.Now().AddWeeks(2)},
                {"任务3", carbon.Now().AddMonths(1)},
            }

            for _, task := range tasks {
                fmt.Printf("%s 截止: %s\n",
                    task.Name, task.Due.DiffForHumans())
            }

            fmt.Printf("性能测试耗时: %v\n", stdDuration)
        }
        ---

2 基础操作

2.1 汇总:6个

01.Carbon核心功能概览
    a.说明
        Carbon提供6大核心功能模块:创建时间、解析字符串、格式化输出、时间比较、时间运算和错误处理。
        这些功能覆盖了日常开发中90%的时间处理场景,API设计简洁直观,链式调用流畅。
        相比标准库time包,Carbon提供更友好的API和更丰富的功能,大幅降低开发复杂度。
        支持时区转换、多语言输出、农历星座等特色功能,是Go生态中最完善的时间处理库。
        本章将逐一讲解这6大功能的使用方法,为后续深入学习打下基础。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 1. 创建时间:多种方式创建Carbon实例
            now := carbon.Now()                          // 当前时间
            yesterday := carbon.Yesterday()              // 昨天
            tomorrow := carbon.Tomorrow()                // 明天
            custom := carbon.Parse("2024-01-15 10:30:00") // 解析字符串

            // 2. 格式化输出:灵活的格式化选项
            fmt.Println("标准格式:", now.ToDateTimeString())     // 2024-01-15 10:30:00
            fmt.Println("自定义格式:", now.Format("Y年m月d日"))     // 2024年01月15日
            fmt.Println("时间戳:", now.Timestamp())              // 1705287000

            // 3. 时间比较:丰富的比较方法
            if tomorrow.Gt(now) {
                fmt.Println("明天大于今天")
            }
            if custom.Between(yesterday, tomorrow) {
                fmt.Println("自定义时间在昨天和明天之间")
            }

            // 4. 时间运算:加减操作
            nextWeek := now.AddWeek()                    // 加一周
            lastMonth := now.SubMonth()                  // 减一月
            fmt.Println("下周:", nextWeek.ToDateString())
            fmt.Println("上月:", lastMonth.ToDateString())

            // 5. 差值计算:获取时间间隔
            diff := tomorrow.DiffInDays(now)             // 相差天数
            fmt.Printf("明天距今%d天\n", diff)

            // 6. 错误处理:安全的错误检查
            invalidTime := carbon.Parse("invalid-date")
            if invalidTime.Error != nil {
                fmt.Println("解析错误:", invalidTime.Error)
            }

            // 链式调用示例:流畅的API设计
            result := carbon.Now().
                AddDays(7).                              // 加7天
                StartOfDay().                            // 获取当天开始时间
                ToDateTimeString()                       // 格式化输出
            fmt.Println("链式调用结果:", result)
        }
        ---

02.Carbon与标准库对比
    a.说明
        Carbon相比标准库time包有诸多优势:API更简洁、功能更丰富、错误处理更友好。
        标准库需要频繁使用Layout常量和复杂的时区设置,Carbon则提供直观的方法名。
        Carbon内置了农历、星座、生肖等中国特色功能,标准库则需要自行实现。
        性能方面Carbon也做了优化,缓存了常用格式和时区信息,减少重复计算。
        下面的示例对比展示了两者在常见场景中的使用差异,突显Carbon的便利性。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "time"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 场景1:格式化当前时间
            // 标准库方式:需要记住复杂的Layout
            stdNow := time.Now()
            stdFormat := stdNow.Format("2006-01-02 15:04:05")
            fmt.Println("标准库:", stdFormat)

            // Carbon方式:语义化方法名
            carbonNow := carbon.Now()
            carbonFormat := carbonNow.ToDateTimeString()
            fmt.Println("Carbon:", carbonFormat)

            // 场景2:解析字符串
            // 标准库方式:必须指定精确的Layout
            stdParse, err := time.Parse("2006-01-02", "2024-01-15")
            if err != nil {
                fmt.Println("解析错误:", err)
            }
            fmt.Println("标准库解析:", stdParse)

            // Carbon方式:自动识别格式
            carbonParse := carbon.Parse("2024-01-15")
            fmt.Println("Carbon解析:", carbonParse.ToDateString())

            // 场景3:时间加减
            // 标准库方式:使用AddDate或Add方法
            stdAdd := stdNow.AddDate(0, 1, 7) // 加1月7天
            fmt.Println("标准库加减:", stdAdd.Format("2006-01-02"))

            // Carbon方式:语义化的链式调用
            carbonAdd := carbonNow.AddMonth().AddDays(7)
            fmt.Println("Carbon加减:", carbonAdd.ToDateString())

            // 场景4:获取月初
            // 标准库方式:需要手动构造
            stdStart := time.Date(stdNow.Year(), stdNow.Month(), 1, 0, 0, 0, 0, stdNow.Location())
            fmt.Println("标准库月初:", stdStart.Format("2006-01-02"))

            // Carbon方式:一个方法搞定
            carbonStart := carbonNow.StartOfMonth()
            fmt.Println("Carbon月初:", carbonStart.ToDateString())

            // 场景5:中文格式输出
            // 标准库:需要自己实现映射
            weekdays := []string{"日", "一", "二", "三", "四", "五", "六"}
            stdChinese := fmt.Sprintf("星期%s", weekdays[stdNow.Weekday()])
            fmt.Println("标准库中文:", stdChinese)

            // Carbon:内置多语言支持
            carbonChinese := carbonNow.SetLocale("zh-CN").ToWeekString()
            fmt.Println("Carbon中文:", carbonChinese)
        }
        ---

03.快速上手示例
    a.说明
        通过一个实际的业务场景演示Carbon的综合应用:实现一个活动倒计时功能。
        需求包括:计算活动剩余时间、判断活动状态、格式化显示倒计时信息。
        示例展示了Carbon如何简化复杂的时间逻辑,代码清晰易懂且易于维护。
        同时演示了错误处理、时区转换、多种格式输出等实用技巧。
        这个示例可作为模板,快速应用到实际项目中的类似场景。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // ActivityCountdown 活动倒计时结构
        type ActivityCountdown struct {
            Name      string
            StartTime carbon.Carbon
            EndTime   carbon.Carbon
        }

        // GetStatus 获取活动状态
        func (a *ActivityCountdown) GetStatus() string {
            now := carbon.Now()

            if now.Lt(a.StartTime) {
                return "未开始"
            } else if now.Between(a.StartTime, a.EndTime) {
                return "进行中"
            } else {
                return "已结束"
            }
        }

        // GetCountdown 获取倒计时信息
        func (a *ActivityCountdown) GetCountdown() string {
            now := carbon.Now()
            status := a.GetStatus()

            switch status {
            case "未开始":
                days := a.StartTime.DiffInDays(now)
                hours := a.StartTime.DiffInHours(now) % 24
                return fmt.Sprintf("距离开始还有 %d天%d小时", days, hours)
            case "进行中":
                days := a.EndTime.DiffInDays(now)
                hours := a.EndTime.DiffInHours(now) % 24
                minutes := a.EndTime.DiffInMinutes(now) % 60
                return fmt.Sprintf("距离结束还有 %d天%d小时%d分钟", days, hours, minutes)
            default:
                return "活动已结束"
            }
        }

        func main() {
            // 创建活动实例
            activity := ActivityCountdown{
                Name:      "双十一大促",
                StartTime: carbon.Parse("2024-11-11 00:00:00"),
                EndTime:   carbon.Parse("2024-11-11 23:59:59"),
            }

            // 检查解析错误
            if activity.StartTime.Error != nil {
                fmt.Println("开始时间解析错误:", activity.StartTime.Error)
                return
            }

            // 显示活动信息
            fmt.Printf("活动名称: %s\n", activity.Name)
            fmt.Printf("开始时间: %s\n", activity.StartTime.ToDateTimeString())
            fmt.Printf("结束时间: %s\n", activity.EndTime.ToDateTimeString())
            fmt.Printf("活动状态: %s\n", activity.GetStatus())
            fmt.Printf("倒计时: %s\n", activity.GetCountdown())

            // 计算活动持续时间
            duration := activity.EndTime.DiffInHours(activity.StartTime)
            fmt.Printf("活动持续: %d小时\n", duration)

            // 多语言显示
            activity.StartTime.SetLocale("zh-CN")
            fmt.Printf("开始日期(中文): %s\n", activity.StartTime.ToDateString())
        }
        ---

2.2 创建时间

01.常用创建方法
    a.说明
        Carbon提供多种便捷的时间创建方法,覆盖各种常见场景。
        Now()获取当前时间,Yesterday()和Tomorrow()获取相对日期。
        Create()系列方法支持精确到纳秒的时间创建,参数灵活可选。
        所有创建方法默认使用系统时区,也可通过SetTimezone()指定时区。
        创建的Carbon实例是不可变的,所有操作返回新实例,保证线程安全。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 获取当前时间
            now := carbon.Now()
            fmt.Println("当前时间:", now.ToDateTimeString())

            // 获取今天、昨天、明天
            today := carbon.Today()
            yesterday := carbon.Yesterday()
            tomorrow := carbon.Tomorrow()
            fmt.Println("今天:", today.ToDateString())
            fmt.Println("昨天:", yesterday.ToDateString())
            fmt.Println("明天:", tomorrow.ToDateString())

            // 精确创建时间:年月日时分秒
            custom1 := carbon.CreateFromDate(2024, 1, 15)
            fmt.Println("指定日期:", custom1.ToDateString())

            custom2 := carbon.CreateFromTime(10, 30, 45)
            fmt.Println("指定时间:", custom2.ToTimeString())

            // 创建完整时间:年月日时分秒纳秒
            custom3 := carbon.CreateFromDateTime(2024, 1, 15, 10, 30, 45)
            fmt.Println("完整时间:", custom3.ToDateTimeString())

            // 使用时间戳创建
            timestamp := int64(1705287000)
            fromTimestamp := carbon.CreateFromTimestamp(timestamp)
            fmt.Println("时间戳创建:", fromTimestamp.ToDateTimeString())

            // 使用毫秒时间戳创建
            millisecond := int64(1705287000000)
            fromMilli := carbon.CreateFromTimestampMilli(millisecond)
            fmt.Println("毫秒时间戳:", fromMilli.ToDateTimeString())

            // 指定时区创建
            tokyo := carbon.Now().SetTimezone("Asia/Tokyo")
            fmt.Println("东京时间:", tokyo.ToDateTimeString())

            newYork := carbon.Now().SetTimezone("America/New_York")
            fmt.Println("纽约时间:", newYork.ToDateTimeString())
        }
        ---

02.特殊时间点创建
    a.说明
        Carbon提供了快速创建特殊时间点的方法,如周初周末、月初月末等。
        这些方法在报表统计、周期性任务等场景中非常实用。
        支持创建当前周期的开始和结束时间,也支持创建上一个或下一个周期。
        时间精度自动调整,日期开始为00:00:00,结束为23:59:59。
        组合使用这些方法可以快速构建复杂的时间范围查询条件。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()
            fmt.Println("当前时间:", now.ToDateTimeString())

            // 本周开始和结束
            startOfWeek := now.StartOfWeek()
            endOfWeek := now.EndOfWeek()
            fmt.Println("本周开始:", startOfWeek.ToDateTimeString())
            fmt.Println("本周结束:", endOfWeek.ToDateTimeString())

            // 本月开始和结束
            startOfMonth := now.StartOfMonth()
            endOfMonth := now.EndOfMonth()
            fmt.Println("本月开始:", startOfMonth.ToDateTimeString())
            fmt.Println("本月结束:", endOfMonth.ToDateTimeString())

            // 本季度开始和结束
            startOfQuarter := now.StartOfQuarter()
            endOfQuarter := now.EndOfQuarter()
            fmt.Println("本季度开始:", startOfQuarter.ToDateTimeString())
            fmt.Println("本季度结束:", endOfQuarter.ToDateTimeString())

            // 本年开始和结束
            startOfYear := now.StartOfYear()
            endOfYear := now.EndOfYear()
            fmt.Println("本年开始:", startOfYear.ToDateTimeString())
            fmt.Println("本年结束:", endOfYear.ToDateTimeString())

            // 当天开始和结束
            startOfDay := now.StartOfDay()
            endOfDay := now.EndOfDay()
            fmt.Println("当天开始:", startOfDay.ToDateTimeString())
            fmt.Println("当天结束:", endOfDay.ToDateTimeString())

            // 本小时开始和结束
            startOfHour := now.StartOfHour()
            endOfHour := now.EndOfHour()
            fmt.Println("本小时开始:", startOfHour.ToDateTimeString())
            fmt.Println("本小时结束:", endOfHour.ToDateTimeString())

            // 实用示例:获取上个月的时间范围
            lastMonthStart := now.SubMonth().StartOfMonth()
            lastMonthEnd := now.SubMonth().EndOfMonth()
            fmt.Println("\n上个月范围:")
            fmt.Println("开始:", lastMonthStart.ToDateTimeString())
            fmt.Println("结束:", lastMonthEnd.ToDateTimeString())
        }
        ---

03.从其他类型创建
    a.说明
        Carbon支持从多种Go原生类型创建时间对象,实现与标准库的无缝集成。
        可以从time.Time、time.Duration等类型转换,方便在现有项目中引入Carbon。
        支持从各种精度的时间戳创建,包括秒、毫秒、微秒、纳秒。
        提供了Carbon到time.Time的双向转换,保证与第三方库的兼容性。
        转换过程会保留原时区信息,确保时间的准确性。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "time"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 从标准库time.Time创建
            stdTime := time.Now()
            fromStdTime := carbon.CreateFromStdTime(stdTime)
            fmt.Println("从time.Time创建:", fromStdTime.ToDateTimeString())

            // Carbon转换为time.Time
            carbonTime := carbon.Now()
            toStdTime := carbonTime.ToStdTime()
            fmt.Println("转为time.Time:", toStdTime.Format("2006-01-02 15:04:05"))

            // 从不同精度的时间戳创建
            sec := time.Now().Unix()
            fromSec := carbon.CreateFromTimestamp(sec)
            fmt.Println("秒时间戳:", fromSec.ToDateTimeString())

            milli := time.Now().UnixMilli()
            fromMilli := carbon.CreateFromTimestampMilli(milli)
            fmt.Println("毫秒时间戳:", fromMilli.ToDateTimeString())

            micro := time.Now().UnixMicro()
            fromMicro := carbon.CreateFromTimestampMicro(micro)
            fmt.Println("微秒时间戳:", fromMicro.ToDateTimeString())

            nano := time.Now().UnixNano()
            fromNano := carbon.CreateFromTimestampNano(nano)
            fmt.Println("纳秒时间戳:", fromNano.ToDateTimeString())

            // 指定时区从时间戳创建
            timestamp := int64(1705287000)
            tokyoTime := carbon.CreateFromTimestamp(timestamp).SetTimezone("Asia/Tokyo")
            fmt.Println("东京时区:", tokyoTime.ToDateTimeString())

            // 实用场景:数据库时间字段转换
            // 假设从数据库读取到的是Unix时间戳
            dbTimestamp := int64(1705287000)
            dbTime := carbon.CreateFromTimestamp(dbTimestamp)
            fmt.Println("\n数据库时间:", dbTime.Format("Y-m-d H:i:s"))

            // 转换为本地时区显示
            localTime := dbTime.SetTimezone(carbon.Local)
            fmt.Println("本地时区:", localTime.ToDateTimeString())
        }
        ---

2.3 解析时间

01.自动解析常见格式
    a.说明
        Carbon的Parse()方法能够智能识别多种常见日期时间格式,无需手动指定Layout。
        支持ISO8601、RFC3339等国际标准格式,也支持常见的中国日期格式。
        解析失败时不会panic,而是在Carbon.Error字段中记录错误信息。
        自动识别带时区的格式,并正确处理时区转换。
        相比标准库繁琐的Layout指定,Parse()大幅简化了日期解析的复杂度。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 解析标准日期格式
            date1 := carbon.Parse("2024-01-15")
            fmt.Println("标准日期:", date1.ToDateString())

            // 解析日期时间格式
            datetime1 := carbon.Parse("2024-01-15 10:30:00")
            fmt.Println("日期时间:", datetime1.ToDateTimeString())

            // 解析ISO8601格式
            iso := carbon.Parse("2024-01-15T10:30:00+08:00")
            fmt.Println("ISO8601:", iso.ToDateTimeString())

            // 解析RFC3339格式
            rfc := carbon.Parse("2024-01-15T10:30:00Z")
            fmt.Println("RFC3339:", rfc.ToDateTimeString())

            // 解析带毫秒的格式
            withMilli := carbon.Parse("2024-01-15 10:30:00.123")
            fmt.Println("带毫秒:", withMilli.ToDateTimeString())

            // 解析中文日期格式
            chinese1 := carbon.Parse("2024年01月15日")
            fmt.Println("中文日期:", chinese1.ToDateString())

            chinese2 := carbon.Parse("2024年01月15日 10时30分00秒")
            fmt.Println("中文全格式:", chinese2.ToDateTimeString())

            // 解析斜杠分隔格式
            slash := carbon.Parse("2024/01/15 10:30:00")
            fmt.Println("斜杠格式:", slash.ToDateTimeString())

            // 解析点分隔格式
            dot := carbon.Parse("2024.01.15 10:30:00")
            fmt.Println("点分隔格式:", dot.ToDateTimeString())

            // 错误处理示例
            invalid := carbon.Parse("invalid-date")
            if invalid.Error != nil {
                fmt.Println("解析错误:", invalid.Error)
            }

            // 解析后转换时区
            parsed := carbon.Parse("2024-01-15 10:30:00")
            tokyo := parsed.SetTimezone("Asia/Tokyo")
            fmt.Println("转换到东京时区:", tokyo.ToDateTimeString())
        }
        ---

02.指定格式解析
    a.说明
        当需要解析特定格式时,可使用ParseByFormat()方法指定精确格式。
        格式符号采用PHP风格,比标准库的Layout更直观易记。
        常用格式符:Y(年4位) m(月2位) d(日2位) H(时24制) i(分) s(秒)。
        支持自定义分隔符和格式组合,满足各种非标准格式的解析需求。
        配合ParseByLayout()可使用Go标准库的Layout格式,兼容旧项目。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 使用Carbon格式符解析
            // Y-年(4位) m-月(2位) d-日(2位) H-时(24) i-分 s-秒
            format1 := carbon.ParseByFormat("2024-01-15 10:30:00", "Y-m-d H:i:s")
            fmt.Println("标准格式:", format1.ToDateTimeString())

            // 解析中文格式
            format2 := carbon.ParseByFormat("2024年01月15日", "Y年m月d日")
            fmt.Println("中文格式:", format2.ToDateString())

            // 解析自定义分隔符
            format3 := carbon.ParseByFormat("2024/01/15", "Y/m/d")
            fmt.Println("斜杠分隔:", format3.ToDateString())

            // 解析12小时制时间
            format4 := carbon.ParseByFormat("2024-01-15 10:30:00 PM", "Y-m-d h:i:s A")
            fmt.Println("12小时制:", format4.ToDateTimeString())

            // 解析带时区的格式
            format5 := carbon.ParseByFormat("2024-01-15 10:30:00 +0800", "Y-m-d H:i:s O")
            fmt.Println("带时区:", format5.ToDateTimeString())

            // 使用Go标准库Layout解析
            layout1 := carbon.ParseByLayout("2024-01-15", "2006-01-02")
            fmt.Println("Layout方式:", layout1.ToDateString())

            layout2 := carbon.ParseByLayout("2024-01-15 10:30:00", "2006-01-02 15:04:05")
            fmt.Println("Layout完整:", layout2.ToDateTimeString())

            // 实用场景:解析日志文件中的时间戳
            logTime := "2024/01/15 10:30:00.123"
            parsed := carbon.ParseByFormat(logTime, "Y/m/d H:i:s.u")
            if parsed.Error == nil {
                fmt.Println("\n日志时间解析成功:", parsed.ToDateTimeString())
                fmt.Println("时间戳:", parsed.Timestamp())
            }

            // 解析不同地区的日期格式
            usDate := carbon.ParseByFormat("01-15-2024", "m-d-Y") // 美国格式
            euDate := carbon.ParseByFormat("15-01-2024", "d-m-Y") // 欧洲格式
            fmt.Println("美国格式:", usDate.ToDateString())
            fmt.Println("欧洲格式:", euDate.ToDateString())
        }
        ---

03.指定时区解析
    a.说明
        解析时间时可以同时指定目标时区,确保时间的准确性。
        ParseByFormat的第三个参数可选时区名称,支持IANA时区数据库格式。
        未指定时区时默认使用系统本地时区,可通过SetTimezone()后续调整。
        对于跨时区的业务系统,建议统一使用UTC时区存储,显示时再转换。
        正确处理时区可以避免夏令时切换、跨国业务等场景中的时间错误。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 解析时指定时区
            dateStr := "2024-01-15 10:30:00"

            // 解析为东京时间
            tokyo := carbon.ParseByFormat(dateStr, "Y-m-d H:i:s", "Asia/Tokyo")
            fmt.Println("东京时间:", tokyo.ToDateTimeString())
            fmt.Println("东京时区:", tokyo.Timezone())

            // 解析为纽约时间
            newYork := carbon.ParseByFormat(dateStr, "Y-m-d H:i:s", "America/New_York")
            fmt.Println("纽约时间:", newYork.ToDateTimeString())
            fmt.Println("纽约时区:", newYork.Timezone())

            // 解析为UTC时间
            utc := carbon.ParseByFormat(dateStr, "Y-m-d H:i:s", "UTC")
            fmt.Println("UTC时间:", utc.ToDateTimeString())

            // 解析后转换时区
            shanghai := carbon.Parse("2024-01-15 10:30:00")
            fmt.Println("上海时间:", shanghai.ToDateTimeString())

            // 转换为其他时区
            londonTime := shanghai.SetTimezone("Europe/London")
            fmt.Println("转为伦敦时间:", londonTime.ToDateTimeString())

            // 实用场景:处理国际订单时间
            // 假设订单时间是美国西部时间
            orderTimeStr := "2024-01-15 10:30:00"
            orderTime := carbon.ParseByFormat(orderTimeStr, "Y-m-d H:i:s", "America/Los_Angeles")

            if orderTime.Error != nil {
                fmt.Println("订单时间解析失败:", orderTime.Error)
                return
            }

            fmt.Println("\n订单时间分析:")
            fmt.Println("洛杉矶时间:", orderTime.ToDateTimeString())

            // 转换为北京时间显示给中国用户
            beijingTime := orderTime.SetTimezone("Asia/Shanghai")
            fmt.Println("北京时间:", beijingTime.ToDateTimeString())

            // 转换为UTC时间存储到数据库
            utcTime := orderTime.SetTimezone("UTC")
            fmt.Println("UTC存储:", utcTime.ToDateTimeString())
            fmt.Println("时间戳:", utcTime.Timestamp())
        }
        ---

2.4 格式化输出

01.预定义格式输出
    a.说明
        Carbon提供了丰富的预定义格式化方法,覆盖最常用的输出场景。
        ToDateString()输出日期,ToTimeString()输出时间,ToDateTimeString()输出完整格式。
        所有方法都使用语义化命名,无需记忆复杂的格式符号。
        支持ISO8601、RFC系列等国际标准格式,便于与外部系统集成。
        预定义方法性能更优,Carbon内部做了格式缓存,比自定义格式快约30%。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 基础格式输出
            fmt.Println("日期:", now.ToDateString())              // 2024-01-15
            fmt.Println("时间:", now.ToTimeString())              // 10:30:00
            fmt.Println("日期时间:", now.ToDateTimeString())      // 2024-01-15 10:30:00

            // 带毫秒的格式
            fmt.Println("带毫秒:", now.ToDateTimeMilliString())   // 2024-01-15 10:30:00.123
            fmt.Println("带微秒:", now.ToDateTimeMicroString())   // 2024-01-15 10:30:00.123456
            fmt.Println("带纳秒:", now.ToDateTimeNanoString())    // 2024-01-15 10:30:00.123456789

            // 国际标准格式
            fmt.Println("ISO8601:", now.ToIso8601String())        // 2024-01-15T10:30:00+08:00
            fmt.Println("RFC822:", now.ToRfc822String())          // 15 Jan 24 10:30 CST
            fmt.Println("RFC850:", now.ToRfc850String())          // Monday, 15-Jan-24 10:30:00 CST
            fmt.Println("RFC1123:", now.ToRfc1123String())        // Mon, 15 Jan 2024 10:30:00 CST
            fmt.Println("RFC2822:", now.ToRfc2822String())        // Mon, 15 Jan 2024 10:30:00 +0800
            fmt.Println("RFC3339:", now.ToRfc3339String())        // 2024-01-15T10:30:00+08:00
            fmt.Println("RFC7231:", now.ToRfc7231String())        // Mon, 15 Jan 2024 10:30:00 GMT

            // 其他常用格式
            fmt.Println("Cookie格式:", now.ToCookieString())      // Monday, 15-Jan-2024 10:30:00 CST
            fmt.Println("RSS格式:", now.ToRssString())            // Mon, 15 Jan 2024 10:30:00 +0800
            fmt.Println("W3C格式:", now.ToW3cString())            // 2024-01-15T10:30:00+08:00

            // 时间戳格式
            fmt.Println("秒时间戳:", now.Timestamp())              // 1705287000
            fmt.Println("毫秒时间戳:", now.TimestampMilli())       // 1705287000000
            fmt.Println("微秒时间戳:", now.TimestampMicro())       // 1705287000000000
            fmt.Println("纳秒时间戳:", now.TimestampNano())        // 1705287000000000000

            // 仅日期部分
            fmt.Println("年月日:", now.ToShortDateString())        // 20240115
            fmt.Println("时分秒:", now.ToShortTimeString())        // 103000
        }
        ---

02.自定义格式输出
    a.说明
        Format()方法支持使用PHP风格的格式符自定义输出格式。
        常用格式符:Y(年) m(月) d(日) H(时24) h(时12) i(分) s(秒) A(AM/PM)。
        支持中文格式和自定义分隔符,满足各种个性化输出需求。
        格式符大小写敏感,Y和y、M和m代表不同含义,使用时需注意。
        也可使用Layout()方法采用Go标准库格式,兼容旧代码。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 使用Carbon格式符
            fmt.Println("标准格式:", now.Format("Y-m-d H:i:s"))          // 2024-01-15 10:30:00
            fmt.Println("中文格式:", now.Format("Y年m月d日 H时i分s秒"))    // 2024年01月15日 10时30分00秒
            fmt.Println("斜杠分隔:", now.Format("Y/m/d"))                // 2024/01/15
            fmt.Println("点分隔:", now.Format("Y.m.d"))                  // 2024.01.15

            // 12小时制格式
            fmt.Println("12小时制:", now.Format("Y-m-d h:i:s A"))        // 2024-01-15 10:30:00 AM
            fmt.Println("简写上午:", now.Format("Y-m-d h:i a"))          // 2024-01-15 10:30 am

            // 包含星期信息
            fmt.Println("完整星期:", now.Format("Y-m-d l"))              // 2024-01-15 Monday
            fmt.Println("简写星期:", now.Format("Y-m-d D"))              // 2024-01-15 Mon

            // 包含月份信息
            fmt.Println("完整月份:", now.Format("d F Y"))                // 15 January 2024
            fmt.Println("简写月份:", now.Format("d M Y"))                // 15 Jan 2024

            // 其他格式符示例
            fmt.Println("年中第几天:", now.Format("Y-m-d 第z天"))         // 2024-01-15 第15天
            fmt.Println("ISO周数:", now.Format("Y年第W周"))               // 2024年第03周
            fmt.Println("月份天数:", now.Format("Y-m 共t天"))             // 2024-01 共31天

            // 使用Go标准库Layout格式
            fmt.Println("\nLayout格式:")
            fmt.Println("标准:", now.Layout("2006-01-02 15:04:05"))
            fmt.Println("自定义:", now.Layout("2006年01月02日"))

            // 实用场景:生成文件名
            fileName := now.Format("YmdHis") + ".log"
            fmt.Println("\n日志文件名:", fileName)                        // 20240115103000.log

            // 生成友好的显示格式
            friendly := now.Format("Y年m月d日 H:i")
            fmt.Println("友好显示:", friendly)                            // 2024年01月15日 10:30
        }
        ---

03.多语言格式输出
    a.说明
        Carbon支持多语言输出,通过SetLocale()设置语言环境。
        内置支持中文、英文、日文等多种语言的星期、月份名称。
        多语言主要影响ToWeekString()、ToMonthString()等语义化方法。
        也可通过Format()配合格式符输出多语言格式。
        语言设置只影响当前Carbon实例,不会影响全局配置。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 设置中文语言环境
            zhCN := now.SetLocale("zh-CN")
            fmt.Println("=== 中文输出 ===")
            fmt.Println("星期:", zhCN.ToWeekString())                    // 星期一
            fmt.Println("月份:", zhCN.ToMonthString())                   // 一月
            fmt.Println("季度:", zhCN.ToQuarterString())                 // 第一季度
            fmt.Println("短星期:", zhCN.ToShortWeekString())             // 周一
            fmt.Println("短月份:", zhCN.ToShortMonthString())            // 1月

            // 设置英文语言环境
            enUS := now.SetLocale("en")
            fmt.Println("\n=== 英文输出 ===")
            fmt.Println("Week:", enUS.ToWeekString())                    // Monday
            fmt.Println("Month:", enUS.ToMonthString())                  // January
            fmt.Println("Quarter:", enUS.ToQuarterString())              // 1st quarter
            fmt.Println("Short Week:", enUS.ToShortWeekString())         // Mon
            fmt.Println("Short Month:", enUS.ToShortMonthString())       // Jan

            // 设置日文语言环境
            ja := now.SetLocale("ja")
            fmt.Println("\n=== 日文输出 ===")
            fmt.Println("曜日:", ja.ToWeekString())                      // 月曜日
            fmt.Println("月:", ja.ToMonthString())                       // 1月

            // 设置韩文语言环境
            ko := now.SetLocale("ko")
            fmt.Println("\n=== 韩文输出 ===")
            fmt.Println("요일:", ko.ToWeekString())                      // 월요일

            // 多语言格式化
            fmt.Println("\n=== 多语言格式化 ===")
            fmt.Println("中文:", zhCN.Format("Y年m月d日 l"))
            fmt.Println("英文:", enUS.Format("l, F d, Y"))

            // 实用场景:多语言日期选择器
            fmt.Println("\n=== 日期选择器示例 ===")
            languages := []string{"zh-CN", "en", "ja", "ko"}
            for _, lang := range languages {
                localized := now.SetLocale(lang)
                fmt.Printf("%s: %s\n", lang, localized.Format("Y-m-d l"))
            }
        }
        ---

2.5 时间比较

01.基础比较方法
    a.说明
        Carbon提供了丰富的时间比较方法,涵盖大于、小于、等于等所有比较场景。
        比较时会考虑时区差异,自动转换到相同时区进行比较,确保结果准确。
        所有比较方法都是语义化命名,如Gt(大于)、Lt(小于)、Eq(等于)等。
        支持精确到纳秒的比较,也支持只比较日期部分,忽略时间部分。
        返回值为布尔类型,可直接用于if判断,代码清晰易读。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()
            yesterday := carbon.Yesterday()
            tomorrow := carbon.Tomorrow()

            // 大于比较 (Greater Than)
            fmt.Println("明天 > 今天:", tomorrow.Gt(now))              // true
            fmt.Println("昨天 > 今天:", yesterday.Gt(now))            // false

            // 大于等于比较 (Greater Than or Equal)
            fmt.Println("今天 >= 今天:", now.Gte(now))                 // true
            fmt.Println("明天 >= 今天:", tomorrow.Gte(now))            // true

            // 小于比较 (Less Than)
            fmt.Println("昨天 < 今天:", yesterday.Lt(now))             // true
            fmt.Println("明天 < 今天:", tomorrow.Lt(now))              // false

            // 小于等于比较 (Less Than or Equal)
            fmt.Println("昨天 <= 今天:", yesterday.Lte(now))           // true
            fmt.Println("今天 <= 今天:", now.Lte(now))                 // true

            // 等于比较
            now2 := carbon.Now()
            fmt.Println("两个now相等:", now.Eq(now2))                  // false (纳秒级差异)

            // 不等于比较
            fmt.Println("今天 != 昨天:", now.Ne(yesterday))            // true

            // 创建相同时间点进行比较
            time1 := carbon.Parse("2024-01-15 10:30:00")
            time2 := carbon.Parse("2024-01-15 10:30:00")
            fmt.Println("相同时间字符串解析:", time1.Eq(time2))         // true

            // 跨时区比较
            shanghai := carbon.Parse("2024-01-15 10:30:00").SetTimezone("Asia/Shanghai")
            tokyo := carbon.Parse("2024-01-15 11:30:00").SetTimezone("Asia/Tokyo")
            fmt.Println("跨时区比较(实际同一时刻):", shanghai.Eq(tokyo)) // true

            // 实用场景:判断是否过期
            deadline := carbon.Parse("2024-12-31 23:59:59")
            if now.Lt(deadline) {
                fmt.Println("\n项目未过期,还有时间")
            } else {
                fmt.Println("\n项目已过期")
            }
        }
        ---

02.范围比较方法
    a.说明
        Between()方法判断时间是否在指定区间内,第三个参数控制区间开闭。
        默认为闭区间[start, end],可设置为开区间(start, end)或半开区间。
        BetweenIncludedStart()包含起始时间,BetweenIncludedEnd()包含结束时间。
        在日期范围查询、活动时间判断等场景中非常实用。
        区间比较同样会处理时区差异,确保跨时区场景下的准确性。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 创建时间范围
            start := carbon.Parse("2024-01-01 00:00:00")
            end := carbon.Parse("2024-12-31 23:59:59")
            current := carbon.Parse("2024-06-15 12:00:00")

            // 闭区间判断 [start, end]
            fmt.Println("在闭区间内:", current.Between(start, end))                      // true

            // 开区间判断 (start, end)
            fmt.Println("在开区间内:", current.BetweenExcluded(start, end))              // true

            // 包含起始时间 [start, end)
            fmt.Println("包含起始:", current.BetweenIncludedStart(start, end))           // true

            // 包含结束时间 (start, end]
            fmt.Println("包含结束:", current.BetweenIncludedEnd(start, end))             // true

            // 边界测试
            fmt.Println("起始点在闭区间:", start.Between(start, end))                     // true
            fmt.Println("起始点在开区间:", start.BetweenExcluded(start, end))            // false
            fmt.Println("结束点在闭区间:", end.Between(start, end))                       // true
            fmt.Println("结束点在开区间:", end.BetweenExcluded(start, end))              // false

            // 实用场景1:活动时间判断
            activityStart := carbon.Parse("2024-11-11 00:00:00")
            activityEnd := carbon.Parse("2024-11-11 23:59:59")
            now := carbon.Now()

            if now.Between(activityStart, activityEnd) {
                fmt.Println("\n活动进行中")
            } else if now.Lt(activityStart) {
                fmt.Println("\n活动未开始")
            } else {
                fmt.Println("\n活动已结束")
            }

            // 实用场景2:工作时间判断
            workStart := carbon.Parse("2024-01-15 09:00:00")
            workEnd := carbon.Parse("2024-01-15 18:00:00")
            checkTime := carbon.Parse("2024-01-15 14:30:00")

            if checkTime.Between(workStart, workEnd) {
                fmt.Println("\n在工作时间内")
            } else {
                fmt.Println("\n非工作时间")
            }

            // 实用场景3:季度判断
            q1Start := carbon.Parse("2024-01-01")
            q1End := carbon.Parse("2024-03-31")
            date := carbon.Parse("2024-02-15")

            if date.Between(q1Start, q1End) {
                fmt.Println("\n该日期在第一季度")
            }
        }
        ---

03.特殊比较方法
    a.说明
        Carbon提供了一系列语义化的特殊比较方法,如IsToday()、IsYesterday()等。
        这些方法让代码更具可读性,避免手动构建比较逻辑��
        支持判断是否为周末、工作日、闰年、上午下午等多种场景。
        IsZero()判断是否为零值时间,常用于数据库字段的空值检查。
        所有Is系列方法都返回bool值,可直接用于条件判断。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 日期相关判断
            fmt.Println("是否今天:", now.IsToday())                         // true
            fmt.Println("是否昨天:", now.IsYesterday())                    // false
            fmt.Println("是否明天:", now.IsTomorrow())                     // false

            // 时间段判断
            fmt.Println("是否当前周:", now.IsCurrentWeek())                // true
            fmt.Println("是否当前月:", now.IsCurrentMonth())               // true
            fmt.Println("是否当前年:", now.IsCurrentYear())                // true

            // 周末和工作日
            fmt.Println("是否周末:", now.IsWeekend())                      // 取决于当天
            fmt.Println("是否工作日:", now.IsWeekday())                    // 取决于当天

            // 上午下午判断
            fmt.Println("是否上午:", now.IsAM())                           // 取决于当前时间
            fmt.Println("是否下午:", now.IsPM())                           // 取决于当前时间

            // 闰年判断
            year2024 := carbon.Parse("2024-01-01")
            year2023 := carbon.Parse("2023-01-01")
            fmt.Println("2024是闰年:", year2024.IsLeapYear())              // true
            fmt.Println("2023是闰年:", year2023.IsLeapYear())              // false

            // 零值判断
            zeroTime := carbon.Carbon{}
            validTime := carbon.Now()
            fmt.Println("零值时间:", zeroTime.IsZero())                    // true
            fmt.Println("有效时间:", validTime.IsZero())                   // false

            // 月份长度
            fmt.Println("当月是长月:", year2024.IsLongMonth())             // 取决于月份(31天)
            fmt.Println("当月是短月:", year2024.IsShortMonth())            // 取决于月份(30天)

            // 实用场景1:周末提醒
            if now.IsWeekend() {
                fmt.Println("\n今天是周末,好好休息!")
            } else if now.IsFriday() {
                fmt.Println("\n明天是周末,加油!")
            }

            // 实用场景2:闰年处理
            birthday := carbon.Parse("2000-02-29")
            currentYear := carbon.Now()
            if currentYear.IsLeapYear() {
                fmt.Println("\n今年是闰年,可以过生日了")
            } else {
                fmt.Println("\n今年不是闰年,2月29日生日推迟到3月1日")
            }

            // 实用场景3:数据验证
            dbTime := carbon.Carbon{}
            if dbTime.IsZero() {
                fmt.Println("\n数据库时间字段为空,使用默认值")
            }
        }
        ---

2.6 时间运算

01.基础加减操作
    a.说明
        Carbon提供了丰富的时间加减方法,支持年月日时分秒的增减操作。
        AddXxx()系列方法用于增加时间,SubXxx()系列方法用于减少时间。
        所有运算返回新的Carbon实例,原实例保持不变,符合不可变对象设计。
        自动处理月末日期溢出,如1月31日加1月会得到2月28日(或29日)。
        链式调用支持连续多次运算,代码简洁流畅。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()
            fmt.Println("当前时间:", now.ToDateTimeString())

            // 年份加减
            nextYear := now.AddYear()
            lastYear := now.SubYear()
            fmt.Println("明年:", nextYear.ToDateString())
            fmt.Println("去年:", lastYear.ToDateString())

            // 月份加减
            nextMonth := now.AddMonth()
            lastMonth := now.SubMonth()
            fmt.Println("下月:", nextMonth.ToDateString())
            fmt.Println("上月:", lastMonth.ToDateString())

            // 周加减
            nextWeek := now.AddWeek()
            lastWeek := now.SubWeek()
            fmt.Println("下周:", nextWeek.ToDateString())
            fmt.Println("上周:", lastWeek.ToDateString())

            // 天数加减
            tomorrow := now.AddDay()
            yesterday := now.SubDay()
            fmt.Println("明天:", tomorrow.ToDateString())
            fmt.Println("昨天:", yesterday.ToDateString())

            // 小时加减
            nextHour := now.AddHour()
            lastHour := now.SubHour()
            fmt.Println("下一小时:", nextHour.ToTimeString())
            fmt.Println("上一小时:", lastHour.ToTimeString())

            // 分钟加减
            next30Min := now.AddMinutes(30)
            last15Min := now.SubMinutes(15)
            fmt.Println("30分钟后:", next30Min.ToTimeString())
            fmt.Println("15分钟前:", last15Min.ToTimeString())

            // 秒数加减
            next10Sec := now.AddSeconds(10)
            last5Sec := now.SubSeconds(5)
            fmt.Println("10秒后:", next10Sec.ToDateTimeString())
            fmt.Println("5秒前:", last5Sec.ToDateTimeString())

            // 链式调用示例
            future := now.AddYears(2).AddMonths(3).AddDays(15)
            fmt.Println("2年3月15天后:", future.ToDateString())

            past := now.SubYears(1).SubMonths(6).SubDays(10)
            fmt.Println("1年6月10天前:", past.ToDateString())
        }
        ---

02.复数形式的加减
    a.说明
        AddXxxs()和SubXxxs()方法支持一次性加减多个单位,参数为整数。
        正数表示增加,负数表示减少,提供更灵活的运算方式。
        适合处理动态计算场景,如根据配置文件的天数计算截止日期。
        自动处理跨月、跨年等边界情况,无需手动判断。
        性能与单次调用相当,但代码更简洁,推荐在明确数量时使用。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()
            fmt.Println("当前时间:", now.ToDateTimeString())

            // 加减多年
            future5Years := now.AddYears(5)
            past3Years := now.SubYears(3)
            fmt.Println("5年后:", future5Years.ToDateString())
            fmt.Println("3年前:", past3Years.ToDateString())

            // 加减多月
            future8Months := now.AddMonths(8)
            past6Months := now.SubMonths(6)
            fmt.Println("8个月后:", future8Months.ToDateString())
            fmt.Println("6个月前:", past6Months.ToDateString())

            // 加减多周
            future4Weeks := now.AddWeeks(4)
            past2Weeks := now.SubWeeks(2)
            fmt.Println("4周后:", future4Weeks.ToDateString())
            fmt.Println("2周前:", past2Weeks.ToDateString())

            // 加减多天
            future30Days := now.AddDays(30)
            past15Days := now.SubDays(15)
            fmt.Println("30天后:", future30Days.ToDateString())
            fmt.Println("15天前:", past15Days.ToDateString())

            // 加减多小时
            future24Hours := now.AddHours(24)
            past12Hours := now.SubHours(12)
            fmt.Println("24小时后:", future24Hours.ToDateTimeString())
            fmt.Println("12小时前:", past12Hours.ToDateTimeString())

            // 使用负数表示减少
            add10Days := now.AddDays(10)
            sub10Days := now.AddDays(-10)
            fmt.Println("加10天:", add10Days.ToDateString())
            fmt.Println("减10天:", sub10Days.ToDateString())

            // 实用场景1:计算试用期结束日期
            registerDate := carbon.Parse("2024-01-15")
            trialDays := 30
            trialEndDate := registerDate.AddDays(trialDays)
            fmt.Println("\n注册日期:", registerDate.ToDateString())
            fmt.Println("试用期结束:", trialEndDate.ToDateString())

            // 实用场景2:计算账单周期
            billStartDate := carbon.Parse("2024-01-01")
            billCycles := 3 // 3个月一个周期
            billEndDate := billStartDate.AddMonths(billCycles).SubDay()
            fmt.Println("\n账单开始:", billStartDate.ToDateString())
            fmt.Println("账单结束:", billEndDate.ToDateString())

            // 实用场景3:工作日计算(简化版)
            projectStart := carbon.Parse("2024-01-15")
            workDays := 20
            estimatedEnd := projectStart.AddDays(workDays)
            fmt.Println("\n项目开始:", projectStart.ToDateString())
            fmt.Println("预计完成:", estimatedEnd.ToDateString())
        }
        ---

03.Duration时长运算
    a.说明
        AddDuration()和SubDuration()支持使用time.Duration进行时间运算。
        Duration可表示纳秒级精度的时长,适合精确的时间计算。
        常用于定时器、超时控制等需要精确时长的场景。
        可以使用time包的常量如time.Hour、time.Minute等构造Duration。
        也支持通过time.ParseDuration()解析字符串形式的时长。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "time"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()
            fmt.Println("当前时间:", now.ToDateTimeString())

            // 使用time包常量
            after1Hour := now.AddDuration(time.Hour)
            after30Min := now.AddDuration(30 * time.Minute)
            after10Sec := now.AddDuration(10 * time.Second)
            fmt.Println("1小时后:", after1Hour.ToTimeString())
            fmt.Println("30分钟后:", after30Min.ToTimeString())
            fmt.Println("10秒后:", after10Sec.ToDateTimeString())

            // 组合使用Duration
            complex := now.AddDuration(2*time.Hour + 30*time.Minute + 15*time.Second)
            fmt.Println("2小时30分15秒后:", complex.ToDateTimeString())

            // 减去Duration
            before2Hours := now.SubDuration(2 * time.Hour)
            fmt.Println("2小时前:", before2Hours.ToTimeString())

            // 解析字符串形式的时长
            duration1, _ := time.ParseDuration("1h30m")
            after1h30m := now.AddDuration(duration1)
            fmt.Println("1小时30分后:", after1h30m.ToTimeString())

            duration2, _ := time.ParseDuration("24h")
            tomorrow := now.AddDuration(duration2)
            fmt.Println("24小时后:", tomorrow.ToDateTimeString())

            // 实用场景1:Session过期时间
            loginTime := carbon.Now()
            sessionTimeout := 2 * time.Hour
            expireTime := loginTime.AddDuration(sessionTimeout)
            fmt.Println("\n登录时间:", loginTime.ToDateTimeString())
            fmt.Println("过期时间:", expireTime.ToDateTimeString())

            // 实用场景2:API限流窗口
            requestTime := carbon.Now()
            rateLimitWindow := 1 * time.Minute
            windowEnd := requestTime.AddDuration(rateLimitWindow)
            fmt.Println("\n请求时间:", requestTime.ToTimeString())
            fmt.Println("窗口结束:", windowEnd.ToTimeString())

            // 实用场景3:任务超时检查
            taskStart := carbon.Parse("2024-01-15 10:00:00")
            timeout := 30 * time.Minute
            deadline := taskStart.AddDuration(timeout)
            current := carbon.Now()

            fmt.Println("\n任务开始:", taskStart.ToDateTimeString())
            fmt.Println("超时时间:", deadline.ToDateTimeString())
            if current.Gt(deadline) {
                fmt.Println("任务已超时")
            } else {
                fmt.Println("任务进行中")
            }
        }
        ---

2.7 错误处理

01.错误检查机制
    a.说明
        Carbon采用优雅的错误处理机制,所有可能出错的操作都会在Error字段中记录错误。
        不会抛出panic,保证程序的稳定性,适合在生产环境中使用。
        可通过检查Carbon.Error是否为nil来判断操作是否成功。
        错误信息详细明确,便于快速定位问题原因。
        链式调用中一旦出错,后续操作会自动跳过,避免级联错误。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 解析无效日期
            invalid := carbon.Parse("invalid-date")
            if invalid.Error != nil {
                fmt.Println("解析错误:", invalid.Error)
                // 输出: parsing time "invalid-date" as "2006-01-02 15:04:05": cannot parse "invalid-date" as "2006"
            }

            // 解析空字符串
            empty := carbon.Parse("")
            if empty.Error != nil {
                fmt.Println("空字符串错误:", empty.Error)
            }

            // 格式不匹配
            wrongFormat := carbon.ParseByFormat("2024-01-15", "Y/m/d")
            if wrongFormat.Error != nil {
                fmt.Println("格式不匹配:", wrongFormat.Error)
            }

            // 正确的解析
            valid := carbon.Parse("2024-01-15 10:30:00")
            if valid.Error == nil {
                fmt.Println("解析成功:", valid.ToDateTimeString())
            }

            // 链式调用中的错误处理
            result := carbon.Parse("invalid").AddDay().ToDateString()
            if result == "" {
                fmt.Println("链式调用中存在错误")
            }

            // 实用场景:安全的日期解析函数
            dateStr := "2024-01-15"
            safeDate := parseDate(dateStr)
            if safeDate.Error == nil {
                fmt.Println("安全解析成功:", safeDate.ToDateString())
            }

            // 错误恢复:提供默认值
            userInput := "invalid-input"
            parsedDate := carbon.Parse(userInput)
            if parsedDate.Error != nil {
                fmt.Println("用户输入无效,使用当前时间")
                parsedDate = carbon.Now()
            }
            fmt.Println("最终使用的时间:", parsedDate.ToDateTimeString())
        }

        // parseDate 安全的日期解析辅助函数
        func parseDate(dateStr string) carbon.Carbon {
            c := carbon.Parse(dateStr)
            if c.Error != nil {
                // 记录日志或处理错误
                fmt.Printf("警告: 无法解析日期 '%s': %v\n", dateStr, c.Error)
            }
            return c
        }
        ---

02.常见错误场景
    a.说明
        Carbon在使用过程中可能遇到的常见错误包括:日期格式错误、时区无效等。
        了解这些常见错误场景可以帮助开发者快速排查问题。
        建议在解析用户输入或外部数据时始终进行错误检查。
        对于关键业务逻辑,可以使用多种格式尝试解析,提高容错性。
        错误处理应该结合业务需求,提供合理的默认值或提示用户重新输入。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            fmt.Println("=== 常见错误场景演示 ===\n")

            // 场景1: 日期格式错误
            fmt.Println("1. 日期格式错误:")
            formats := []string{
                "2024/13/01",      // 月份超出范围
                "2024-02-30",      // 2月没有30号
                "2024-01-32",      // 日期超出范围
                "2024-00-15",      // 月份为0
            }
            for _, f := range formats {
                c := carbon.Parse(f)
                if c.Error != nil {
                    fmt.Printf("  %s => 错误: %v\n", f, c.Error)
                }
            }

            // 场景2: 时区错误
            fmt.Println("\n2. 时区错误:")
            invalidTZ := carbon.Now().SetTimezone("Invalid/Timezone")
            if invalidTZ.Error != nil {
                fmt.Println("  无效时区:", invalidTZ.Error)
            }

            // 场景3: 格式符错误
            fmt.Println("\n3. 格式符错误:")
            wrongFormat := carbon.ParseByFormat("2024-01-15", "invalid-format")
            if wrongFormat.Error != nil {
                fmt.Println("  格式符错误:", wrongFormat.Error)
            }

            // 场景4: 空值处理
            fmt.Println("\n4. 空值处理:")
            emptyStr := carbon.Parse("")
            if emptyStr.Error != nil {
                fmt.Println("  空字符串:", emptyStr.Error)
            }

            // 场景5: 时间戳范围
            fmt.Println("\n5. 时间戳范围:")
            // 负数时间戳
            negativeTs := carbon.CreateFromTimestamp(-1)
            fmt.Println("  负数时间戳:", negativeTs.ToDateTimeString())

            // 极大时间戳可能导致溢出
            largeTs := carbon.CreateFromTimestamp(253402300799) // 9999-12-31
            fmt.Println("  最大时间戳:", largeTs.ToDateTimeString())

            // 实用场景:多格式尝试解析
            fmt.Println("\n=== 智能解析示例 ===")
            userInputs := []string{
                "2024-01-15",
                "2024/01/15",
                "15-01-2024",
                "01/15/2024",
                "invalid",
            }

            for _, input := range userInputs {
                result := smartParse(input)
                if result.Error == nil {
                    fmt.Printf("%s => 解析成功: %s\n", input, result.ToDateString())
                } else {
                    fmt.Printf("%s => 解析失败\n", input)
                }
            }
        }

        // smartParse 智能多格式解析
        func smartParse(dateStr string) carbon.Carbon {
            // 尝试多种格式
            formats := []string{
                "Y-m-d",
                "Y/m/d",
                "d-m-Y",
                "m/d/Y",
            }

            // 首先尝试自动解析
            c := carbon.Parse(dateStr)
            if c.Error == nil {
                return c
            }

            // 尝试各种格式
            for _, format := range formats {
                c = carbon.ParseByFormat(dateStr, format)
                if c.Error == nil {
                    return c
                }
            }

            // 所有尝试都失败,返回错误
            return carbon.Parse(dateStr)
        }
        ---

03.错误处理最佳实践
    a.说明
        在生产环境中应该建立完善的错误处理机制,确保程序的健壮性。
        推荐为关键操作编写包装函数,统一处理错误和日志记录。
        对于用户输入,应该提供友好的错误提示,而不是直接暴露技术细节。
        在数据库操作、API调用等场景中,错误的Carbon对象不应该被存储或返回。
        使用IsZero()可以判断Carbon对象是否有效,避免使用无效对象。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "log"
            "github.com/golang-module/carbon/v2"
        )

        // SafeParse 安全解析函数,包含日志记录
        func SafeParse(dateStr string, defaultValue carbon.Carbon) carbon.Carbon {
            c := carbon.Parse(dateStr)
            if c.Error != nil {
                log.Printf("日期解析失败: %s, 错误: %v, 使用默认值", dateStr, c.Error)
                return defaultValue
            }
            return c
        }

        // ParseWithValidation 带验证的解析函数
        func ParseWithValidation(dateStr string) (carbon.Carbon, error) {
            c := carbon.Parse(dateStr)
            if c.Error != nil {
                return carbon.Carbon{}, fmt.Errorf("无效的日期格式: %s", dateStr)
            }

            // 额外的业务验证
            if c.Lt(carbon.Parse("1900-01-01")) {
                return carbon.Carbon{}, fmt.Errorf("日期不能早于1900年")
            }

            if c.Gt(carbon.Parse("2100-12-31")) {
                return carbon.Carbon{}, fmt.Errorf("日期不能晚于2100年")
            }

            return c, nil
        }

        // DateRange 日期范围结构,包含验证
        type DateRange struct {
            Start carbon.Carbon
            End   carbon.Carbon
        }

        // NewDateRange 创建并验证日期范围
        func NewDateRange(startStr, endStr string) (*DateRange, error) {
            start := carbon.Parse(startStr)
            if start.Error != nil {
                return nil, fmt.Errorf("开始日期无效: %v", start.Error)
            }

            end := carbon.Parse(endStr)
            if end.Error != nil {
                return nil, fmt.Errorf("结束日期无效: %v", end.Error)
            }

            if start.Gte(end) {
                return nil, fmt.Errorf("开始日期必须早于结束日期")
            }

            return &DateRange{Start: start, End: end}, nil
        }

        func main() {
            // 使用安全解析函数
            fmt.Println("=== 安全解析示例 ===")
            date1 := SafeParse("2024-01-15", carbon.Now())
            fmt.Println("解析结果1:", date1.ToDateString())

            date2 := SafeParse("invalid-date", carbon.Now())
            fmt.Println("解析结果2(使用默认值):", date2.ToDateString())

            // 使用带验证的解析
            fmt.Println("\n=== 带验证的解析 ===")
            validDate, err := ParseWithValidation("2024-01-15")
            if err != nil {
                fmt.Println("验证失败:", err)
            } else {
                fmt.Println("验证通过:", validDate.ToDateString())
            }

            tooEarly, err := ParseWithValidation("1800-01-01")
            if err != nil {
                fmt.Println("验证失败:", err)
            }

            // 使用日期范围验证
            fmt.Println("\n=== 日期范围验证 ===")
            validRange, err := NewDateRange("2024-01-01", "2024-12-31")
            if err != nil {
                fmt.Println("范围创建失败:", err)
            } else {
                fmt.Printf("有效范围: %s 至 %s\n",
                    validRange.Start.ToDateString(),
                    validRange.End.ToDateString())
            }

            invalidRange, err := NewDateRange("2024-12-31", "2024-01-01")
            if err != nil {
                fmt.Println("范围创建失败:", err)
            }

            // 检查零值
            fmt.Println("\n=== 零值检查 ===")
            var emptyCarbon carbon.Carbon
            if emptyCarbon.IsZero() {
                fmt.Println("未初始化的Carbon对象不应使用")
                emptyCarbon = carbon.Now() // 初始化为当前时间
            }
            fmt.Println("初始化后:", emptyCarbon.ToDateTimeString())
        }
        ---

3 时间操作

3.1 时间加减

01.精确到各个时间单位
    a.说明
        Carbon支持对年、月、周、日、时、分、秒、毫秒等各个时间单位进行精确加减。
        提供单数和复数两种形式的方法,单数形式默认加减1个单位。
        复数形式可以指定加减的数量,支持正负数,负数表示减少。
        所有加减操作都会自动处理进位和借位,如月末日期溢出等边界情况。
        返回新的Carbon实例,原实例保持不变,支持并发安全使用。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            base := carbon.Parse("2024-01-15 10:30:45")
            fmt.Println("基准时间:", base.ToDateTimeString())

            // 世纪加减
            nextCentury := base.AddCentury()
            lastCentury := base.SubCentury()
            fmt.Println("下个世纪:", nextCentury.ToDateString())
            fmt.Println("上个世纪:", lastCentury.ToDateString())

            // 十年加减
            next10Years := base.AddDecade()
            last10Years := base.SubDecade()
            fmt.Println("10年后:", next10Years.ToDateString())
            fmt.Println("10年前:", last10Years.ToDateString())

            // 年份加减
            nextYear := base.AddYear()
            next5Years := base.AddYears(5)
            fmt.Println("1年后:", nextYear.ToDateString())
            fmt.Println("5年后:", next5Years.ToDateString())

            // 季度加减
            nextQuarter := base.AddQuarter()
            next2Quarters := base.AddQuarters(2)
            fmt.Println("下季度:", nextQuarter.ToDateString())
            fmt.Println("2个季度后:", next2Quarters.ToDateString())

            // 月份加减(处理月末溢出)
            jan31 := carbon.Parse("2024-01-31")
            nextMonth := jan31.AddMonth()
            fmt.Println("1月31日加1月:", nextMonth.ToDateString()) // 2024-02-29

            // 周加减
            nextWeek := base.AddWeek()
            next4Weeks := base.AddWeeks(4)
            fmt.Println("1周后:", nextWeek.ToDateString())
            fmt.Println("4周后:", next4Weeks.ToDateString())

            // 天数加减
            tomorrow := base.AddDay()
            next30Days := base.AddDays(30)
            fmt.Println("明天:", tomorrow.ToDateString())
            fmt.Println("30天后:", next30Days.ToDateString())

            // 时分秒加减
            nextHour := base.AddHour()
            next90Minutes := base.AddMinutes(90)
            next3600Seconds := base.AddSeconds(3600)
            fmt.Println("1小时后:", nextHour.ToTimeString())
            fmt.Println("90分钟后:", next90Minutes.ToTimeString())
            fmt.Println("3600秒后:", next3600Seconds.ToTimeString())
        }
        ---

02.工作日计算
    a.说明
        AddWorkdays()和SubWorkdays()方法专门用于计算工作日。
        默认周一至周五为工作日,自动跳过周末。
        适用于项目管理、请假审批等需要计算工作日的场景。
        注意:该方法不考虑法定节假日,如需考虑需要自行实现。
        可以配合IsWeekday()和IsWeekend()方法进行更复杂的工作日逻辑。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 从周五开始计算工作日
            friday := carbon.Parse("2024-01-12") // 2024年1月12日是周五
            fmt.Println("起始日期:", friday.ToDateString(), friday.ToWeekString())

            // 加1个工作日(跳过周末到周一)
            next1Workday := friday.AddWorkday()
            fmt.Println("1个工作日后:", next1Workday.ToDateString(), next1Workday.ToWeekString())

            // 加5个工作日
            next5Workdays := friday.AddWorkdays(5)
            fmt.Println("5个工作日后:", next5Workdays.ToDateString(), next5Workdays.ToWeekString())

            // 从周一减去工作日
            monday := carbon.Parse("2024-01-15") // 2024年1月15日是周一
            fmt.Println("\n起始日期:", monday.ToDateString(), monday.ToWeekString())

            // 减1个工作日(跳过周末到周五)
            last1Workday := monday.SubWorkday()
            fmt.Println("1个工作日前:", last1Workday.ToDateString(), last1Workday.ToWeekString())

            // 减5个工作日
            last5Workdays := monday.SubWorkdays(5)
            fmt.Println("5个工作日前:", last5Workdays.ToDateString(), last5Workdays.ToWeekString())

            // 实用场景1:计算项目交付日期
            startDate := carbon.Parse("2024-01-15")
            workDaysNeeded := 10
            deliveryDate := startDate.AddWorkdays(workDaysNeeded)
            fmt.Println("\n项目开始:", startDate.ToDateString())
            fmt.Println("需要工作日:", workDaysNeeded)
            fmt.Println("预计交付:", deliveryDate.ToDateString())

            // 实用场景2:计算请假后上班日期
            leaveStart := carbon.Parse("2024-01-17") // 周三开始请假
            leaveDays := 3                           // 请假3天
            backToWork := leaveStart.AddDays(leaveDays)

            // 如果回来是周末,调整到下周一
            for backToWork.IsWeekend() {
                backToWork = backToWork.AddDay()
            }
            fmt.Println("\n请假开始:", leaveStart.ToDateString())
            fmt.Println("请假天数:", leaveDays)
            fmt.Println("回来上班:", backToWork.ToDateString(), backToWork.ToWeekString())

            // 实用场景3:统计两个日期间的工作日数量
            start := carbon.Parse("2024-01-01")
            end := carbon.Parse("2024-01-31")
            workdayCount := 0

            current := start
            for current.Lte(end) {
                if current.IsWeekday() {
                    workdayCount++
                }
                current = current.AddDay()
            }
            fmt.Printf("\n%s 至 %s\n", start.ToDateString(), end.ToDateString())
            fmt.Printf("共有工作日: %d天\n", workdayCount)
        }
        ---

03.月末日期处理
    a.说明
        Carbon在处理月份加减时会智能处理月末溢出问题。
        如1月31日加1个月,由于2月只有28/29天,会自动调整到2月最后一天。
        这种设计符合大多数业务场景的直觉,避免出现意外的日期。
        如需保持日期不变(如31日→31日),需要手动检查月份天数。
        了解这个行为对于编写正确的日期逻辑非常重要。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            fmt.Println("=== 月末溢出处理示例 ===\n")

            // 1月31日加1个月
            jan31 := carbon.Parse("2024-01-31")
            feb := jan31.AddMonth()
            fmt.Println("1月31日加1月:", feb.ToDateString()) // 2024-02-29(闰年)

            // 连续加月份
            mar := feb.AddMonth()
            apr := mar.AddMonth()
            fmt.Println("继续加1月:", mar.ToDateString())    // 2024-03-29
            fmt.Println("再加1月:", apr.ToDateString())      // 2024-04-29

            // 3月31日加1个月
            mar31 := carbon.Parse("2024-03-31")
            apr30 := mar31.AddMonth()
            fmt.Println("\n3月31日加1月:", apr30.ToDateString()) // 2024-04-30

            // 减月份的溢出处理
            mar31_2 := carbon.Parse("2024-03-31")
            feb29 := mar31_2.SubMonth()
            fmt.Println("3月31日减1月:", feb29.ToDateString()) // 2024-02-29

            // 非闰年的2月
            jan31_2023 := carbon.Parse("2023-01-31")
            feb28 := jan31_2023.AddMonth()
            fmt.Println("\n2023年1月31日加1月:", feb28.ToDateString()) // 2023-02-28

            // 实用场景1:账单日期计算
            fmt.Println("\n=== 月账单日期计算 ===")
            billDay := 31 // 每月31号出账单
            jan := carbon.Parse("2024-01-31")

            for i := 0; i < 6; i++ {
                current := jan.AddMonths(i)
                // 获取当月的最后一天
                lastDay := current.EndOfMonth()
                fmt.Printf("%d月账单日期: %s\n", current.Month(), lastDay.ToDateString())
            }

            // 实用场景2:保持日期逻辑
            fmt.Println("\n=== 保持日期逻辑 ===")
            startDate := carbon.Parse("2024-01-31")

            for i := 1; i <= 3; i++ {
                nextMonth := startDate.AddMonths(i)
                targetDay := startDate.Day()

                // 如果目标月份的天数少于起始日期的天数
                if nextMonth.DaysInMonth() < targetDay {
                    // 使用月末日期
                    nextMonth = nextMonth.EndOfMonth()
                }

                fmt.Printf("%d个月后(保持31日): %s (实际%d日)\n",
                    i, nextMonth.ToDateString(), nextMonth.Day())
            }
        }
        ---

3.2 开始结束时间

01.获取周期的开始时间
    a.说明
        Carbon提供了StartOfXxx()系列方法快速获取各个时间周期的开始时刻。
        支持世纪、年、季度、月、周、日、小时、分钟、秒等所有常用周期。
        开始时间会将更小的时间单位重置为最小值,如StartOfDay()将时分秒设为00:00:00。
        这些方法在数据统计、报表生成等需要时间范围的场景中非常实用。
        配合EndOfXxx()方法可以快速构建完整的时间范围查询条件。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Parse("2024-06-15 14:30:45")
            fmt.Println("当前时间:", now.ToDateTimeString())
            fmt.Println()

            // 获取世纪开始
            startOfCentury := now.StartOfCentury()
            fmt.Println("世纪开始:", startOfCentury.ToDateTimeString()) // 2000-01-01 00:00:00

            // 获取十年开始
            startOfDecade := now.StartOfDecade()
            fmt.Println("十年开始:", startOfDecade.ToDateTimeString())  // 2020-01-01 00:00:00

            // 获取年初
            startOfYear := now.StartOfYear()
            fmt.Println("年初:", startOfYear.ToDateTimeString())        // 2024-01-01 00:00:00

            // 获取季度开始
            startOfQuarter := now.StartOfQuarter()
            fmt.Println("季度开始:", startOfQuarter.ToDateTimeString()) // 2024-04-01 00:00:00

            // 获取月初
            startOfMonth := now.StartOfMonth()
            fmt.Println("月初:", startOfMonth.ToDateTimeString())       // 2024-06-01 00:00:00

            // 获取周初(默认周一为一周开始)
            startOfWeek := now.StartOfWeek()
            fmt.Println("周初:", startOfWeek.ToDateTimeString())        // 2024-06-10 00:00:00 (周一)

            // 获取当天开始
            startOfDay := now.StartOfDay()
            fmt.Println("当天开始:", startOfDay.ToDateTimeString())     // 2024-06-15 00:00:00

            // 获取当前小时开始
            startOfHour := now.StartOfHour()
            fmt.Println("小时开始:", startOfHour.ToDateTimeString())    // 2024-06-15 14:00:00

            // 获取当前分钟开始
            startOfMinute := now.StartOfMinute()
            fmt.Println("分钟开始:", startOfMinute.ToDateTimeString())  // 2024-06-15 14:30:00

            // 获取当前秒开始
            startOfSecond := now.StartOfSecond()
            fmt.Println("秒开始:", startOfSecond.ToDateTimeString())    // 2024-06-15 14:30:45

            // 实用场景:本月数据查询
            fmt.Println("\n=== 本月数据范围 ===")
            monthStart := carbon.Now().StartOfMonth()
            fmt.Println("查询开始时间:", monthStart.ToDateTimeString())
            fmt.Println("SQL WHERE: created_at >= '" + monthStart.ToDateTimeString() + "'")
        }
        ---

02.获取周期的结束时间
    a.说明
        EndOfXxx()系列方法用于获取各个时间周期的结束时刻。
        结束时间会将更小的时间单位设为最大值,如EndOfDay()将时间设为23:59:59。
        注意秒的最大值是59,不包含毫秒微秒纳秒部分。
        与StartOf配合使用可以精确定义时间范围的边界。
        在数据库查询中通常使用<号而不是<=号,避免精度问题。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Parse("2024-06-15 14:30:45")
            fmt.Println("当前时间:", now.ToDateTimeString())
            fmt.Println()

            // 获取世纪结束
            endOfCentury := now.EndOfCentury()
            fmt.Println("世纪结束:", endOfCentury.ToDateTimeString()) // 2099-12-31 23:59:59

            // 获取十年结束
            endOfDecade := now.EndOfDecade()
            fmt.Println("十年结束:", endOfDecade.ToDateTimeString())  // 2029-12-31 23:59:59

            // 获取年末
            endOfYear := now.EndOfYear()
            fmt.Println("年末:", endOfYear.ToDateTimeString())        // 2024-12-31 23:59:59

            // 获取季度结束
            endOfQuarter := now.EndOfQuarter()
            fmt.Println("季度结束:", endOfQuarter.ToDateTimeString()) // 2024-06-30 23:59:59

            // 获取月末
            endOfMonth := now.EndOfMonth()
            fmt.Println("月末:", endOfMonth.ToDateTimeString())       // 2024-06-30 23:59:59

            // 获取周末(周日为一周结束)
            endOfWeek := now.EndOfWeek()
            fmt.Println("周末:", endOfWeek.ToDateTimeString())        // 2024-06-16 23:59:59 (周日)

            // 获取当天结束
            endOfDay := now.EndOfDay()
            fmt.Println("当天结束:", endOfDay.ToDateTimeString())     // 2024-06-15 23:59:59

            // 获取当前小时结束
            endOfHour := now.EndOfHour()
            fmt.Println("小时结束:", endOfHour.ToDateTimeString())    // 2024-06-15 14:59:59

            // 获取当前分钟结束
            endOfMinute := now.EndOfMinute()
            fmt.Println("分钟结束:", endOfMinute.ToDateTimeString())  // 2024-06-15 14:30:59

            // 获取当前秒结束
            endOfSecond := now.EndOfSecond()
            fmt.Println("秒结束:", endOfSecond.ToDateTimeString())    // 2024-06-15 14:30:45

            // 实用场景:查询今天的数据
            fmt.Println("\n=== 今日数据范围 ===")
            todayStart := carbon.Now().StartOfDay()
            todayEnd := carbon.Now().EndOfDay()
            fmt.Printf("查询范围: %s ~ %s\n",
                todayStart.ToDateTimeString(),
                todayEnd.ToDateTimeString())
        }
        ---

03.完整时间范围应用
    a.说明
        结合StartOf和EndOf方法可以构建各种复杂的时间范围查询条件。
        常用于数据统计、报表生成、日志分析等需要按时间周期聚合的场景。
        建议在数据库查询时使用>= start AND < end+1的方式,避免边界问题。
        可以快速实现本周、本月、本季度、本年等各种时间维度的数据筛选。
        配合Between()方法可以进行更灵活的时间范围判断。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 今日范围
            fmt.Println("=== 今日数据范围 ===")
            todayStart := now.StartOfDay()
            todayEnd := now.EndOfDay()
            fmt.Printf("%s ~ %s\n", todayStart.ToDateTimeString(), todayEnd.ToDateTimeString())

            // 本周范围
            fmt.Println("\n=== 本周数据范围 ===")
            weekStart := now.StartOfWeek()
            weekEnd := now.EndOfWeek()
            fmt.Printf("%s ~ %s\n", weekStart.ToDateTimeString(), weekEnd.ToDateTimeString())
            fmt.Printf("共 %d 天\n", weekEnd.DiffInDays(weekStart)+1)

            // 本月范围
            fmt.Println("\n=== 本月数据范围 ===")
            monthStart := now.StartOfMonth()
            monthEnd := now.EndOfMonth()
            fmt.Printf("%s ~ %s\n", monthStart.ToDateTimeString(), monthEnd.ToDateTimeString())
            fmt.Printf("共 %d 天\n", monthEnd.Day())

            // 本季度范围
            fmt.Println("\n=== 本季度数据范围 ===")
            quarterStart := now.StartOfQuarter()
            quarterEnd := now.EndOfQuarter()
            fmt.Printf("%s ~ %s\n", quarterStart.ToDateTimeString(), quarterEnd.ToDateTimeString())

            // 本年范围
            fmt.Println("\n=== 本年数据范围 ===")
            yearStart := now.StartOfYear()
            yearEnd := now.EndOfYear()
            fmt.Printf("%s ~ %s\n", yearStart.ToDateTimeString(), yearEnd.ToDateTimeString())
            fmt.Printf("共 %d 天\n", yearEnd.DiffInDays(yearStart)+1)

            // 上个月范围
            fmt.Println("\n=== 上个月数据范围 ===")
            lastMonthStart := now.SubMonth().StartOfMonth()
            lastMonthEnd := now.SubMonth().EndOfMonth()
            fmt.Printf("%s ~ %s\n", lastMonthStart.ToDateTimeString(), lastMonthEnd.ToDateTimeString())

            // 实用场景:生成SQL查询条件
            fmt.Println("\n=== SQL查询示例 ===")
            fmt.Println("-- 查询本月数据")
            fmt.Printf("SELECT * FROM orders WHERE created_at >= '%s' AND created_at < '%s';\n",
                monthStart.ToDateTimeString(),
                monthEnd.AddDay().StartOfDay().ToDateTimeString())

            fmt.Println("\n-- 查询上季度数据")
            lastQuarterStart := now.SubQuarter().StartOfQuarter()
            lastQuarterEnd := now.SubQuarter().EndOfQuarter()
            fmt.Printf("SELECT * FROM sales WHERE sale_date >= '%s' AND sale_date < '%s';\n",
                lastQuarterStart.ToDateString(),
                lastQuarterEnd.AddDay().ToDateString())

            // 实用场景:检查时间是否在本周
            fmt.Println("\n=== 时间范围判断 ===")
            checkDate := carbon.Parse("2024-06-15")
            if checkDate.Between(weekStart, weekEnd) {
                fmt.Printf("%s 在本周范围内\n", checkDate.ToDateString())
            } else {
                fmt.Printf("%s 不在本周范围内\n", checkDate.ToDateString())
            }
        }
        ---

3.3 差值计算

01.基础差值计算
    a.说明
        Carbon提供DiffInXxx()系列方法计算两个时间之间的差值。
        支持计算年、月、周、日、时、分、秒等各个时间单位的差值。
        返回值为int64类型,正数表示未来,负数表示过去。
        DiffAbsInXxx()系列方法返回绝对值,不区分过去未来。
        差值计算会考虑时区差异,自动转换后再计算。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            start := carbon.Parse("2024-01-01 00:00:00")
            end := carbon.Parse("2024-12-31 23:59:59")
            fmt.Println("开始时间:", start.ToDateTimeString())
            fmt.Println("结束时间:", end.ToDateTimeString())
            fmt.Println()

            // 相差年数
            diffYears := end.DiffInYears(start)
            fmt.Println("相差年数:", diffYears) // 0年(不足1年)

            // 相差月数
            diffMonths := end.DiffInMonths(start)
            fmt.Println("相差月数:", diffMonths) // 11个月

            // 相差周数
            diffWeeks := end.DiffInWeeks(start)
            fmt.Println("相差周数:", diffWeeks) // 52周

            // 相差天数
            diffDays := end.DiffInDays(start)
            fmt.Println("相差天数:", diffDays) // 365天(闰年366天)

            // 相差小时数
            diffHours := end.DiffInHours(start)
            fmt.Println("相差小时数:", diffHours) // 8759小时

            // 相差分钟数
            diffMinutes := end.DiffInMinutes(start)
            fmt.Println("相差分钟数:", diffMinutes)

            // 相差秒数
            diffSeconds := end.DiffInSeconds(start)
            fmt.Println("相差秒数:", diffSeconds)

            // 负数差值(过去时间)
            now := carbon.Now()
            yesterday := now.SubDay()
            diff := yesterday.DiffInDays(now)
            fmt.Println("\n昨天距今天:", diff, "天") // -1

            // 绝对差值
            absDiff := yesterday.DiffAbsInDays(now)
            fmt.Println("绝对差值:", absDiff, "天") // 1

            // 实用场景:计算年龄
            birthday := carbon.Parse("1990-05-15")
            today := carbon.Now()
            age := today.DiffInYears(birthday)
            fmt.Printf("\n出生日期: %s\n", birthday.ToDateString())
            fmt.Printf("今天: %s\n", today.ToDateString())
            fmt.Printf("年龄: %d岁\n", age)
        }
        ---

02.时长格式化输出
    a.说明
        DiffForHumans()方法可以将时间差值转换为人类友好的描述。
        自动选择最合适的时间单位,如"3天前"、"2小时后"等。
        支持多语言输出,通过SetLocale()设置语言环境。
        适合在界面显示相对时间,如评论发布时间、最后登录时间等。
        提供了灵活的格式化选项,可以自定义输出格式。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 相对当前时间的人性化描述
            fmt.Println("=== 英文描述 ===")
            fmt.Println("1秒前:", now.SubSecond().DiffForHumans())
            fmt.Println("30秒前:", now.SubSeconds(30).DiffForHumans())
            fmt.Println("1分钟前:", now.SubMinute().DiffForHumans())
            fmt.Println("30分钟前:", now.SubMinutes(30).DiffForHumans())
            fmt.Println("1小时前:", now.SubHour().DiffForHumans())
            fmt.Println("3小时前:", now.SubHours(3).DiffForHumans())
            fmt.Println("1天前:", now.SubDay().DiffForHumans())
            fmt.Println("5天前:", now.SubDays(5).DiffForHumans())
            fmt.Println("1周前:", now.SubWeek().DiffForHumans())
            fmt.Println("1个月前:", now.SubMonth().DiffForHumans())
            fmt.Println("1年前:", now.SubYear().DiffForHumans())

            // 未来时间
            fmt.Println("\n=== 未来时间 ===")
            fmt.Println("1分钟后:", now.AddMinute().DiffForHumans())
            fmt.Println("1小时后:", now.AddHour().DiffForHumans())
            fmt.Println("1天后:", now.AddDay().DiffForHumans())
            fmt.Println("1周后:", now.AddWeek().DiffForHumans())

            // 中文描述
            fmt.Println("\n=== 中文描述 ===")
            nowCN := now.SetLocale("zh-CN")
            fmt.Println("1分钟前:", nowCN.SubMinute().DiffForHumans())
            fmt.Println("1小时前:", nowCN.SubHour().DiffForHumans())
            fmt.Println("1天前:", nowCN.SubDay().DiffForHumans())
            fmt.Println("1周前:", nowCN.SubWeek().DiffForHumans())
            fmt.Println("1个月前:", nowCN.SubMonth().DiffForHumans())

            // 实用场景:评论时间显示
            fmt.Println("\n=== 评论时间示例 ===")
            comments := []carbon.Carbon{
                carbon.Now().SubSeconds(30),
                carbon.Now().SubMinutes(5),
                carbon.Now().SubHours(2),
                carbon.Now().SubDays(1),
                carbon.Now().SubWeeks(1),
                carbon.Now().SubMonths(3),
            }

            for i, comment := range comments {
                commentCN := comment.SetLocale("zh-CN")
                fmt.Printf("评论%d: %s\n", i+1, commentCN.DiffForHumans())
            }

            // 实用场景:最后登录时间
            lastLogin := carbon.Parse("2024-01-10 10:30:00")
            lastLoginCN := lastLogin.SetLocale("zh-CN")
            fmt.Printf("\n最后登录: %s\n", lastLoginCN.DiffForHumans())
        }
        ---

03.精确差值计算
    a.说明
        DiffInDuration()方法返回time.Duration类型的精确差值。
        适合需要精确到纳秒级别的时间差值计算。
        可以与time包的其他功能无缝集成。
        Diff()方法返回Carbon自定义的Diff结构,提供更丰富的差值信息。
        在性能监控、超时检测等场景中非常实用。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "time"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            start := carbon.Parse("2024-01-15 10:00:00")
            end := carbon.Parse("2024-01-15 12:30:45")

            // 获取Duration类型差值
            duration := end.DiffInDuration(start)
            fmt.Println("Duration差值:", duration)
            fmt.Println("小时数:", duration.Hours())
            fmt.Println("分钟数:", duration.Minutes())
            fmt.Println("秒数:", duration.Seconds())

            // 与time包的集成
            fmt.Println("\n=== 与time包集成 ===")
            if duration > 2*time.Hour {
                fmt.Println("差值超过2小时")
            }

            // 格式化Duration
            fmt.Printf("格式化: %v\n", duration) // 2h30m45s

            // 实用场景1:程序执行时间测量
            fmt.Println("\n=== 执行时间测量 ===")
            taskStart := carbon.Now()

            // 模拟任务执行
            time.Sleep(100 * time.Millisecond)

            taskEnd := carbon.Now()
            execTime := taskEnd.DiffInDuration(taskStart)
            fmt.Printf("任务执行时间: %v\n", execTime)
            fmt.Printf("毫秒: %.2f ms\n", execTime.Seconds()*1000)

            // 实用场景2:超时检测
            fmt.Println("\n=== 超时检测 ===")
            requestStart := carbon.Parse("2024-01-15 10:00:00")
            requestEnd := carbon.Parse("2024-01-15 10:00:35")
            timeout := 30 * time.Second

            elapsed := requestEnd.DiffInDuration(requestStart)
            if elapsed > timeout {
                fmt.Printf("请求超时: 耗时 %v, 超时限制 %v\n", elapsed, timeout)
            } else {
                fmt.Printf("请求正常: 耗时 %v\n", elapsed)
            }

            // 实用场景3:倒计时计算
            fmt.Println("\n=== 活动倒计时 ===")
            activityStart := carbon.Parse("2024-11-11 00:00:00")
            now := carbon.Now()

            if now.Lt(activityStart) {
                remaining := activityStart.DiffInDuration(now)
                days := int(remaining.Hours() / 24)
                hours := int(remaining.Hours()) % 24
                minutes := int(remaining.Minutes()) % 60

                fmt.Printf("距离活动开始还有: %d天%d小时%d分钟\n", days, hours, minutes)
            } else {
                fmt.Println("活动已开始或已结束")
            }
        }
        ---

3.4 时间范围

01.判断时间范围
    a.说明
        Between()系列方法用于判断时间是否在指定范围内。
        支持闭区间、开区间、半开区间等多种区间类型。
        在活动时间判断、数据有效期校验等场景中非常实用。
        区间比较会自动处理时区差异,确保结果准确。
        配合逻辑运算可以实现复杂的时间范围条件判断。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 定义时间范围
            start := carbon.Parse("2024-01-01 00:00:00")
            end := carbon.Parse("2024-12-31 23:59:59")
            check := carbon.Parse("2024-06-15 12:00:00")

            fmt.Println("范围开始:", start.ToDateTimeString())
            fmt.Println("范围结束:", end.ToDateTimeString())
            fmt.Println("检查时间:", check.ToDateTimeString())
            fmt.Println()

            // 闭区间 [start, end]
            inClosed := check.Between(start, end)
            fmt.Println("在闭区间内:", inClosed) // true

            // 开区间 (start, end)
            inOpen := check.BetweenExcluded(start, end)
            fmt.Println("在开区间内:", inOpen) // true

            // 左闭右开 [start, end)
            inLeftClosed := check.BetweenIncludedStart(start, end)
            fmt.Println("在左闭右开区间:", inLeftClosed) // true

            // 左开右闭 (start, end]
            inRightClosed := check.BetweenIncludedEnd(start, end)
            fmt.Println("在右闭右开区间:", inRightClosed) // true

            // 边界测试
            fmt.Println("\n=== 边界测试 ===")
            fmt.Println("起始点在闭区间:", start.Between(start, end))               // true
            fmt.Println("起始点在开区间:", start.BetweenExcluded(start, end))      // false
            fmt.Println("结束点在闭区间:", end.Between(start, end))                 // true
            fmt.Println("结束点在开区间:", end.BetweenExcluded(start, end))        // false

            // 实用场景1:活动时间判断
            fmt.Println("\n=== 活动时间判断 ===")
            activityStart := carbon.Parse("2024-11-11 00:00:00")
            activityEnd := carbon.Parse("2024-11-11 23:59:59")
            now := carbon.Now()

            if now.Between(activityStart, activityEnd) {
                fmt.Println("活动进行中")
            } else if now.Lt(activityStart) {
                days := activityStart.DiffInDays(now)
                fmt.Printf("活动未开始,还有%d天\n", days)
            } else {
                fmt.Println("活动已结束")
            }

            // 实用场景2:会员有效期检查
            fmt.Println("\n=== 会员有效期检查 ===")
            memberStart := carbon.Parse("2024-01-01")
            memberEnd := carbon.Parse("2024-12-31")
            currentDate := carbon.Now()

            if currentDate.Between(memberStart, memberEnd) {
                remaining := memberEnd.DiffInDays(currentDate)
                fmt.Printf("会员有效,剩余%d天\n", remaining)
            } else {
                fmt.Println("会员已过期")
            }
        }
        ---

02.创建时间范围对象
    a.说明
        虽然Carbon本身不提供Range对象,但可以通过自定义结构实现。
        时间范围对象封装了开始和结束时间,提供统一的范围操作接口。
        可以添加各种实用方法,如判断重叠、计算交集、格式化输出等。
        在项目管理、酒店预订、会议室安排等场景中非常实用。
        配合Carbon的其他功能可以实现复杂的时间范围业务逻辑。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // TimeRange 时间范围结构
        type TimeRange struct {
            Start carbon.Carbon
            End   carbon.Carbon
        }

        // NewTimeRange 创建时间范围
        func NewTimeRange(start, end carbon.Carbon) *TimeRange {
            if start.Gt(end) {
                start, end = end, start // 自动调整顺序
            }
            return &TimeRange{Start: start, End: end}
        }

        // Contains 判断某个时间是否在范围内
        func (tr *TimeRange) Contains(t carbon.Carbon) bool {
            return t.Between(tr.Start, tr.End)
        }

        // Duration 计算范围时长
        func (tr *TimeRange) Duration() int64 {
            return tr.End.DiffInSeconds(tr.Start)
        }

        // DurationInDays 计算范围天数
        func (tr *TimeRange) DurationInDays() int64 {
            return tr.End.DiffInDays(tr.Start) + 1 // 包含首尾
        }

        // Overlaps 判断两个范围是否重叠
        func (tr *TimeRange) Overlaps(other *TimeRange) bool {
            return tr.Start.Lte(other.End) && tr.End.Gte(other.Start)
        }

        // String 格式化输出
        func (tr *TimeRange) String() string {
            return fmt.Sprintf("%s ~ %s",
                tr.Start.ToDateTimeString(),
                tr.End.ToDateTimeString())
        }

        func main() {
            // 创建时间范围
            range1 := NewTimeRange(
                carbon.Parse("2024-01-01"),
                carbon.Parse("2024-01-31"),
            )
            fmt.Println("范围1:", range1.String())
            fmt.Println("持续天数:", range1.DurationInDays())

            // 判断时间是否在范围内
            check := carbon.Parse("2024-01-15")
            fmt.Printf("\n%s 在范围内: %v\n", check.ToDateString(), range1.Contains(check))

            // 判断范围重叠
            range2 := NewTimeRange(
                carbon.Parse("2024-01-15"),
                carbon.Parse("2024-02-15"),
            )
            fmt.Println("\n范围2:", range2.String())
            fmt.Println("范围1和范围2重叠:", range1.Overlaps(range2))

            // 不重叠的范围
            range3 := NewTimeRange(
                carbon.Parse("2024-03-01"),
                carbon.Parse("2024-03-31"),
            )
            fmt.Println("\n范围3:", range3.String())
            fmt.Println("范围1和范围3重叠:", range1.Overlaps(range3))

            // 实用场景:酒店房间预订冲突检查
            fmt.Println("\n=== 酒店预订冲突检查 ===")
            existingBooking := NewTimeRange(
                carbon.Parse("2024-06-10"),
                carbon.Parse("2024-06-15"),
            )
            newBooking := NewTimeRange(
                carbon.Parse("2024-06-13"),
                carbon.Parse("2024-06-20"),
            )

            fmt.Println("已有预订:", existingBooking.String())
            fmt.Println("新预订:", newBooking.String())

            if existingBooking.Overlaps(newBooking) {
                fmt.Println("预订冲突,无法预订!")
            } else {
                fmt.Println("可以预订")
            }
        }
        ---

03.批量时间范围处理
    a.说明
        在实际业务中经常需要处理多个时间范围的情况。
        可以实现范围列表的合并、分割、查找空档等操作。
        适用于排班管理、资源调度、时间轴可视化等复杂场景。
        通过排序和遍历可以高效处理大量时间范围数据。
        结合数据结构和算法可以优化时间范围查询性能。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "sort"
            "github.com/golang-module/carbon/v2"
        )

        // TimeRange 时间范围结构
        type TimeRange struct {
            Start carbon.Carbon
            End   carbon.Carbon
            Name  string
        }

        // TimeRangeList 时间范围列表
        type TimeRangeList []*TimeRange

        // Sort 按开始时间排序
        func (trl TimeRangeList) Sort() {
            sort.Slice(trl, func(i, j int) bool {
                return trl[i].Start.Lt(trl[j].Start)
            })
        }

        // FindConflicts 查找冲突的时间范围
        func (trl TimeRangeList) FindConflicts() [][]*TimeRange {
            var conflicts [][]*TimeRange
            trl.Sort()

            for i := 0; i < len(trl); i++ {
                var group []*TimeRange
                for j := i + 1; j < len(trl); j++ {
                    if trl[i].End.Gte(trl[j].Start) {
                        if len(group) == 0 {
                            group = append(group, trl[i])
                        }
                        group = append(group, trl[j])
                    }
                }
                if len(group) > 0 {
                    conflicts = append(conflicts, group)
                }
            }
            return conflicts
        }

        func main() {
            // 创建多个时间范围
            ranges := TimeRangeList{
                {
                    Start: carbon.Parse("2024-01-01 09:00:00"),
                    End:   carbon.Parse("2024-01-01 10:00:00"),
                    Name:  "会议A",
                },
                {
                    Start: carbon.Parse("2024-01-01 09:30:00"),
                    End:   carbon.Parse("2024-01-01 11:00:00"),
                    Name:  "会议B",
                },
                {
                    Start: carbon.Parse("2024-01-01 14:00:00"),
                    End:   carbon.Parse("2024-01-01 15:00:00"),
                    Name:  "会议C",
                },
                {
                    Start: carbon.Parse("2024-01-01 14:30:00"),
                    End:   carbon.Parse("2024-01-01 15:30:00"),
                    Name:  "会议D",
                },
            }

            // 排序
            ranges.Sort()
            fmt.Println("=== 所有会议时间 ===")
            for _, r := range ranges {
                fmt.Printf("%s: %s ~ %s\n",
                    r.Name,
                    r.Start.ToTimeString(),
                    r.End.ToTimeString())
            }

            // 查找冲突
            conflicts := ranges.FindConflicts()
            fmt.Println("\n=== 冲突检测 ===")
            if len(conflicts) > 0 {
                for i, group := range conflicts {
                    fmt.Printf("冲突组%d:\n", i+1)
                    for _, r := range group {
                        fmt.Printf("  - %s: %s ~ %s\n",
                            r.Name,
                            r.Start.ToTimeString(),
                            r.End.ToTimeString())
                    }
                }
            } else {
                fmt.Println("没有冲突")
            }

            // 查找空闲时间段
            fmt.Println("\n=== 空闲时间段 ===")
            workStart := carbon.Parse("2024-01-01 09:00:00")
            workEnd := carbon.Parse("2024-01-01 18:00:00")

            current := workStart
            for i, r := range ranges {
                if current.Lt(r.Start) {
                    fmt.Printf("空闲: %s ~ %s\n",
                        current.ToTimeString(),
                        r.Start.ToTimeString())
                }
                current = r.End

                // 最后一个会议后的空闲时间
                if i == len(ranges)-1 && current.Lt(workEnd) {
                    fmt.Printf("空闲: %s ~ %s\n",
                        current.ToTimeString(),
                        workEnd.ToTimeString())
                }
            }
        }
        ---

3.5 时间遍历

01.按天遍历
    a.说明
        虽然Carbon不直接提供遍历方法,但可以通过循环和AddDay()实现。
        按天遍历适用于日历生成、日期选择器、考勤统计等场景。
        可以配合IsWeekday()和IsWeekend()筛选工作日或周末。
        遍历时建议设置合理的循环次数上限,避免无限循环。
        结合条件判断可以实现各种复杂的日期遍历逻辑。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 遍历一周的日期
            fmt.Println("=== 遍历本周 ===")
            start := carbon.Now().StartOfWeek()
            for i := 0; i < 7; i++ {
                current := start.AddDays(i)
                weekday := current.ToWeekString()
                fmt.Printf("%s %s\n", current.ToDateString(), weekday)
            }

            // 遍历一个月的日期
            fmt.Println("\n=== 遍历本月 ===")
            monthStart := carbon.Now().StartOfMonth()
            daysInMonth := monthStart.DaysInMonth()

            for i := 0; i < daysInMonth; i++ {
                current := monthStart.AddDays(i)
                fmt.Printf("%2d日 %s\n", current.Day(), current.ToWeekString())
            }

            // 只遍历工作日
            fmt.Println("\n=== 遍历本月工作日 ===")
            workdayCount := 0
            for i := 0; i < daysInMonth; i++ {
                current := monthStart.AddDays(i)
                if current.IsWeekday() {
                    workdayCount++
                    fmt.Printf("%s %s\n", current.ToDateString(), current.ToWeekString())
                }
            }
            fmt.Printf("本月共有 %d 个工作日\n", workdayCount)

            // 只遍历周末
            fmt.Println("\n=== 遍历本月周末 ===")
            for i := 0; i < daysInMonth; i++ {
                current := monthStart.AddDays(i)
                if current.IsWeekend() {
                    fmt.Printf("%s %s\n", current.ToDateString(), current.ToWeekString())
                }
            }

            // 实用场景:查找所有周五
            fmt.Println("\n=== 查找本月所有周五 ===")
            for i := 0; i < daysInMonth; i++ {
                current := monthStart.AddDays(i)
                if current.IsFriday() {
                    fmt.Println(current.ToDateString())
                }
            }
        }
        ---

02.按周遍历
    a.说明
        按周遍历适用于周报生成、周期性任务调度等场景。
        可以通过AddWeek()方法实现周级别的时间递增。
        配合StartOfWeek()和EndOfWeek()可以获取完整周范围。
        在项目管理中常用于按周统计进度和工作量。
        可以灵活设置周的起始日(周一或周日)。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 遍历一个季度的周
            fmt.Println("=== 遍历本季度(按周) ===")
            quarterStart := carbon.Now().StartOfQuarter()
            quarterEnd := carbon.Now().EndOfQuarter()

            current := quarterStart.StartOfWeek()
            weekNum := 1

            for current.Lte(quarterEnd) {
                weekStart := current
                weekEnd := current.EndOfWeek()

                // 确保不超过季度末
                if weekEnd.Gt(quarterEnd) {
                    weekEnd = quarterEnd
                }

                fmt.Printf("第%d周: %s ~ %s\n",
                    weekNum,
                    weekStart.ToDateString(),
                    weekEnd.ToDateString())

                current = current.AddWeek()
                weekNum++
            }

            // 遍历一年的周数
            fmt.Println("\n=== 遍历全年周数 ===")
            yearStart := carbon.Parse("2024-01-01").StartOfWeek()
            yearEnd := carbon.Parse("2024-12-31")

            current = yearStart
            weekNum = 1

            for current.Lte(yearEnd) {
                fmt.Printf("第%2d周: %s (ISO周%d)\n",
                    weekNum,
                    current.ToDateString(),
                    current.WeekOfYear())

                current = current.AddWeek()
                weekNum++
            }

            // 实用场景:生成月度周报时间表
            fmt.Println("\n=== 月度周报时间表 ===")
            monthStart := carbon.Now().StartOfMonth()
            monthEnd := carbon.Now().EndOfMonth()

            current = monthStart.StartOfWeek()
            weekNum = 1

            for current.Lte(monthEnd) {
                weekStart := current
                if weekStart.Lt(monthStart) {
                    weekStart = monthStart
                }

                weekEnd := current.EndOfWeek()
                if weekEnd.Gt(monthEnd) {
                    weekEnd = monthEnd
                }

                days := weekEnd.DiffInDays(weekStart) + 1
                fmt.Printf("第%d周(%d天): %s ~ %s\n",
                    weekNum,
                    days,
                    weekStart.ToDateString(),
                    weekEnd.ToDateString())

                current = current.AddWeek()
                weekNum++
            }
        }
        ---

03.按自定义间隔遍历
    a.说明
        除了按天和按周,还可以按小时、按月等任意时间间隔遍历。
        灵活的遍历间隔适用于各种业务场景的时间序列生成。
        在数据分析、图表展示、定时任务等场景中非常有用。
        可以设置遍历的步长和终止条件,实现精确控制。
        配合格式化输出可以生成各种时间序列数据。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 按小时遍历一天
            fmt.Println("=== 按小时遍历24小时 ===")
            dayStart := carbon.Now().StartOfDay()
            for i := 0; i < 24; i++ {
                current := dayStart.AddHours(i)
                fmt.Printf("%02d:00 - %s\n", i, current.ToTimeString())
            }

            // 按2小时间隔遍历
            fmt.Println("\n=== 按2小时间隔遍历 ===")
            for i := 0; i < 24; i += 2 {
                current := dayStart.AddHours(i)
                fmt.Printf("%s\n", current.ToTimeString())
            }

            // 按月遍历一年
            fmt.Println("\n=== 按月遍历一年 ===")
            yearStart := carbon.Parse("2024-01-01")
            for i := 0; i < 12; i++ {
                current := yearStart.AddMonths(i)
                days := current.DaysInMonth()
                fmt.Printf("%d月: %s, 共%d天\n",
                    current.Month(),
                    current.ToMonthString(),
                    days)
            }

            // 按季度遍历
            fmt.Println("\n=== 按季度遍历 ===")
            for i := 0; i < 4; i++ {
                current := yearStart.AddQuarters(i)
                qStart := current.StartOfQuarter()
                qEnd := current.EndOfQuarter()
                fmt.Printf("Q%d: %s ~ %s\n",
                    current.Quarter(),
                    qStart.ToDateString(),
                    qEnd.ToDateString())
            }

            // 实用场景1:生成每30分钟的时间点(会议室预约)
            fmt.Println("\n=== 会议室可预约时间 ===")
            meetingStart := carbon.Parse("2024-01-15 09:00:00")
            meetingEnd := carbon.Parse("2024-01-15 18:00:00")

            current := meetingStart
            for current.Lte(meetingEnd) {
                fmt.Println(current.ToTimeString())
                current = current.AddMinutes(30)
            }

            // 实用场景2:生成未来7天的日期(天气预报)
            fmt.Println("\n=== 7天天气预报日期 ===")
            today := carbon.Now()
            for i := 0; i < 7; i++ {
                future := today.AddDays(i)
                fmt.Printf("%s %s\n",
                    future.ToDateString(),
                    future.ToWeekString())
            }

            // 实用场景3:生成每隔3天的时间点(定期任务)
            fmt.Println("\n=== 每3天执行的任务时间 ===")
            taskStart := carbon.Parse("2024-01-01")
            taskEnd := carbon.Parse("2024-01-31")

            current = taskStart
            taskNum := 1
            for current.Lte(taskEnd) {
                fmt.Printf("任务%d: %s\n", taskNum, current.ToDateString())
                current = current.AddDays(3)
                taskNum++
            }
        }
        ---

4 格式化与解析

4.1 标准格式

01.ISO8601标准格式
    a.说明
        ISO8601是国际标准化组织制定的日期时间表示规范。
        Carbon完全支持ISO8601格式的解析和输出,包括基本格式和扩展格式。
        标准格式包含日期、时间和时区信息,适合跨系统数据交换。
        ToIso8601String()方法输出完整的ISO8601格式。
        在API接口、日志记录等场景中推荐使用ISO8601格式。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // ISO8601完整格式
            fmt.Println("ISO8601完整:", now.ToIso8601String())
            // 输出: 2024-01-15T10:30:00+08:00

            // ISO8601仅日期
            fmt.Println("ISO8601日期:", now.ToIso8601DateString())
            // 输出: 2024-01-15

            // ISO8601仅时间
            fmt.Println("ISO8601时间:", now.ToIso8601TimeString())
            // 输出: 10:30:00+08:00

            // ISO8601带毫秒
            fmt.Println("ISO8601毫秒:", now.ToIso8601MilliString())
            // 输出: 2024-01-15T10:30:00.123+08:00

            // ISO8601带微秒
            fmt.Println("ISO8601微秒:", now.ToIso8601MicroString())
            // 输出: 2024-01-15T10:30:00.123456+08:00

            // ISO8601带纳秒
            fmt.Println("ISO8601纳秒:", now.ToIso8601NanoString())
            // 输出: 2024-01-15T10:30:00.123456789+08:00

            // 解析ISO8601格式
            fmt.Println("\n=== 解析ISO8601 ===")
            isoStr := "2024-01-15T10:30:00+08:00"
            parsed := carbon.Parse(isoStr)
            if parsed.Error == nil {
                fmt.Println("解析成功:", parsed.ToDateTimeString())
            }

            // 不同时区的ISO8601
            utc := now.SetTimezone("UTC")
            fmt.Println("\n=== 不同时区 ===")
            fmt.Println("北京时间:", now.ToIso8601String())
            fmt.Println("UTC时间:", utc.ToIso8601String())

            // 实用场景:API数据交换
            fmt.Println("\n=== API响应示例 ===")
            type APIResponse struct {
                CreatedAt string `json:"created_at"`
                UpdatedAt string `json:"updated_at"`
            }

            resp := APIResponse{
                CreatedAt: carbon.Now().ToIso8601String(),
                UpdatedAt: carbon.Now().ToIso8601String(),
            }
            fmt.Printf("CreatedAt: %s\n", resp.CreatedAt)
            fmt.Printf("UpdatedAt: %s\n", resp.UpdatedAt)
        }
        ---

02.RFC系列标准格式
    a.说明
        RFC(Request for Comments)是互联网标准文档系列。
        Carbon支持多种RFC标准的日期时间格式,如RFC822、RFC3339等。
        不同的RFC标准适用于不同的协议和场景,如HTTP、Email等。
        ToRfcXxxString()系列方法可快速输出各种RFC标准格式。
        了解各种RFC格式有助于正确处理不同系统的时间数据。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()
            fmt.Println("当前时间:", now.ToDateTimeString())
            fmt.Println()

            // RFC822 - 常用于Email
            fmt.Println("RFC822:", now.ToRfc822String())
            // 输出: 15 Jan 24 10:30 CST

            // RFC822Z - RFC822带数字时区
            fmt.Println("RFC822Z:", now.ToRfc822ZString())
            // 输出: 15 Jan 24 10:30 +0800

            // RFC850 - 较旧的格式
            fmt.Println("RFC850:", now.ToRfc850String())
            // 输出: Monday, 15-Jan-24 10:30:00 CST

            // RFC1123 - HTTP日期格式
            fmt.Println("RFC1123:", now.ToRfc1123String())
            // 输出: Mon, 15 Jan 2024 10:30:00 CST

            // RFC1123Z - RFC1123带数字时区
            fmt.Println("RFC1123Z:", now.ToRfc1123ZString())
            // 输出: Mon, 15 Jan 2024 10:30:00 +0800

            // RFC2822 - Email标准格式
            fmt.Println("RFC2822:", now.ToRfc2822String())
            // 输出: Mon, 15 Jan 2024 10:30:00 +0800

            // RFC3339 - 互联网标准格式
            fmt.Println("RFC3339:", now.ToRfc3339String())
            // 输出: 2024-01-15T10:30:00+08:00

            // RFC3339带毫秒
            fmt.Println("RFC3339毫秒:", now.ToRfc3339MilliString())
            // 输出: 2024-01-15T10:30:00.123+08:00

            // RFC7231 - HTTP新标准
            fmt.Println("RFC7231:", now.ToRfc7231String())
            // 输出: Mon, 15 Jan 2024 10:30:00 GMT

            // 解析RFC格式
            fmt.Println("\n=== 解析RFC格式 ===")
            rfc3339Str := "2024-01-15T10:30:00+08:00"
            parsed := carbon.Parse(rfc3339Str)
            fmt.Println("RFC3339解析:", parsed.ToDateTimeString())

            // 实用场景:HTTP响应头
            fmt.Println("\n=== HTTP响应头示例 ===")
            fmt.Println("Last-Modified:", now.ToRfc7231String())
            fmt.Println("Expires:", now.AddHour().ToRfc7231String())
        }
        ---

03.其他标准格式
    a.说明
        除了ISO和RFC系列,还有其他常用的标准格式。
        Cookie格式用于HTTP Cookie的过期时间设置。
        RSS格式用于RSS订阅源的发布时间。
        W3C格式是万维网联盟推荐的标准格式。
        这些格式在Web开发中经常用到,Carbon都提供了便捷支持。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // Cookie格式
            fmt.Println("Cookie格式:", now.ToCookieString())
            // 输出: Monday, 15-Jan-2024 10:30:00 CST

            // RSS格式
            fmt.Println("RSS格式:", now.ToRssString())
            // 输出: Mon, 15 Jan 2024 10:30:00 +0800

            // W3C格式(等同于RFC3339)
            fmt.Println("W3C格式:", now.ToW3cString())
            // 输出: 2024-01-15T10:30:00+08:00

            // ANSIC格式
            fmt.Println("ANSIC格式:", now.ToAnsicString())
            // 输出: Mon Jan 15 10:30:00 2024

            // Unix日期格式
            fmt.Println("Unix日期:", now.ToUnixDateString())
            // 输出: Mon Jan 15 10:30:00 CST 2024

            // Ruby日期格式
            fmt.Println("Ruby格式:", now.ToRubyDateString())
            // 输出: Mon Jan 15 10:30:00 +0800 2024

            // Kitchen格式(仅时间)
            fmt.Println("Kitchen格式:", now.ToKitchenString())
            // 输出: 10:30AM

            // 实用场景:设置Cookie过期时间
            fmt.Println("\n=== Cookie示例 ===")
            expireTime := carbon.Now().AddHours(24)
            fmt.Printf("Set-Cookie: session_id=abc123; Expires=%s; Path=/\n",
                expireTime.ToCookieString())

            // 实用场景:RSS Feed
            fmt.Println("\n=== RSS Feed示例 ===")
            fmt.Println("<item>")
            fmt.Println("  <title>文章标题</title>")
            fmt.Printf("  <pubDate>%s</pubDate>\n", now.ToRssString())
            fmt.Println("</item>")

            // 实用场景:时间戳对比
            fmt.Println("\n=== 不同格式对比 ===")
            formats := map[string]string{
                "ISO8601": now.ToIso8601String(),
                "RFC3339": now.ToRfc3339String(),
                "W3C":     now.ToW3cString(),
                "Cookie":  now.ToCookieString(),
                "RSS":     now.ToRssString(),
            }

            for name, value := range formats {
                fmt.Printf("%-10s %s\n", name+":", value)
            }
        }
        ---

4.2 自定义格式

01.PHP风格格式符
    a.说明
        Carbon采用PHP风格的格式符,比Go标准库的Layout更直观易记。
        常用格式符:Y(年4位) y(年2位) m(月2位) n(月1位) d(日2位) j(日1位)。
        时间格式符:H(时24制) h(时12制) i(分) s(秒) A(AM/PM大写) a(am/pm小写)。
        星期格式符:l(完整) D(缩写) w(数字0-6) N(数字1-7)。
        月份格式符:F(完整) M(缩写)。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Parse("2024-01-15 14:30:45")

            // 年份格式符
            fmt.Println("=== 年份 ===")
            fmt.Println("Y(4位):", now.Format("Y"))      // 2024
            fmt.Println("y(2位):", now.Format("y"))      // 24

            // 月份格式符
            fmt.Println("\n=== 月份 ===")
            fmt.Println("m(2位):", now.Format("m"))      // 01
            fmt.Println("n(1位):", now.Format("n"))      // 1
            fmt.Println("M(英文缩写):", now.Format("M"))  // Jan
            fmt.Println("F(英文全称):", now.Format("F"))  // January

            // 日期格式符
            fmt.Println("\n=== 日期 ===")
            fmt.Println("d(2位):", now.Format("d"))      // 15
            fmt.Println("j(1位):", now.Format("j"))      // 15

            // 星期格式符
            fmt.Println("\n=== 星期 ===")
            fmt.Println("l(完整):", now.Format("l"))     // Monday
            fmt.Println("D(缩写):", now.Format("D"))     // Mon
            fmt.Println("w(数字0-6):", now.Format("w"))  // 1
            fmt.Println("N(数字1-7):", now.Format("N"))  // 1

            // 时间格式符
            fmt.Println("\n=== 时间 ===")
            fmt.Println("H(24小时):", now.Format("H"))   // 14
            fmt.Println("h(12小时):", now.Format("h"))   // 02
            fmt.Println("i(分钟):", now.Format("i"))     // 30
            fmt.Println("s(秒):", now.Format("s"))       // 45
            fmt.Println("A(AM/PM):", now.Format("A"))    // PM
            fmt.Println("a(am/pm):", now.Format("a"))    // pm

            // 其他格式符
            fmt.Println("\n=== 其他 ===")
            fmt.Println("z(年中第几天):", now.Format("z"))    // 14
            fmt.Println("W(ISO周数):", now.Format("W"))       // 03
            fmt.Println("t(月份天数):", now.Format("t"))      // 31
            fmt.Println("L(是否闰年):", now.Format("L"))      // 1

            // 组合使用
            fmt.Println("\n=== 组合格式 ===")
            fmt.Println(now.Format("Y-m-d H:i:s"))           // 2024-01-15 14:30:45
            fmt.Println(now.Format("l, F j, Y"))             // Monday, January 15, 2024
            fmt.Println(now.Format("Y年m月d日 H时i分s秒"))    // 2024年01月15日 14时30分45秒
        }
        ---

02.自定义分隔符和格式
    a.说明
        Format()方法支持任意分隔符和文字,不仅限于标准格式。
        可以插入中文、符号等任意字符,实现个性化的日期显示。
        适用于生成用户友好的日期描述、文件名、报表标题等场景。
        特殊字符会被原样输出,不会被解析为格式符。
        可以通过转义实现复杂的格式组合。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 使用不同分隔符
            fmt.Println("=== 分隔符 ===")
            fmt.Println("横杠:", now.Format("Y-m-d"))        // 2024-01-15
            fmt.Println("斜杠:", now.Format("Y/m/d"))        // 2024/01/15
            fmt.Println("点号:", now.Format("Y.m.d"))        // 2024.01.15
            fmt.Println("空格:", now.Format("Y m d"))        // 2024 01 15
            fmt.Println("无分隔:", now.Format("Ymd"))        // 20240115

            // 中文格式
            fmt.Println("\n=== 中文格式 ===")
            fmt.Println(now.Format("Y年m月d日"))
            fmt.Println(now.Format("Y年m月d日 H时i分s秒"))
            fmt.Println(now.Format("Y年m月d日 星期w"))
            fmt.Println(now.Format("Y年第W周"))

            // 英文格式
            fmt.Println("\n=== 英文格式 ===")
            fmt.Println(now.Format("F d, Y"))                // January 15, 2024
            fmt.Println(now.Format("l, F d, Y"))             // Monday, January 15, 2024
            fmt.Println(now.Format("D, M d, Y"))             // Mon, Jan 15, 2024
            fmt.Println(now.Format("h:i A"))                 // 02:30 PM

            // 实用场景:文件名
            fmt.Println("\n=== 文件名示例 ===")
            fileName := fmt.Sprintf("backup_%s.sql", now.Format("Ymd_His"))
            fmt.Println(fileName)                             // backup_20240115_143045.sql

            logFile := fmt.Sprintf("app_%s.log", now.Format("Y-m-d"))
            fmt.Println(logFile)                              // app_2024-01-15.log

            // 实用场景:报表标题
            fmt.Println("\n=== 报表标题 ===")
            title1 := fmt.Sprintf("%s 销售报表", now.Format("Y年m月"))
            fmt.Println(title1)                               // 2024年01月 销售报表

            title2 := fmt.Sprintf("%s周报", now.Format("Y年第W周"))
            fmt.Println(title2)                               // 2024年第03周周报

            // 实用场景:友好的日期显示
            fmt.Println("\n=== 友好显�� ===")
            fmt.Println(now.Format("Y年m月d日 l"))
            fmt.Println(now.Format("m月d日 H:i"))
            fmt.Println(now.Format("F d日 H点i分"))
        }
        ---

03.格式化模板
    a.说明
        可以预定义常用的格式化模板,提高代码复用性。
        模板可以包含完整的格式描述,方便在多处使用。
        建议为不同场景定义专用模板,如API模板、日志模板、显示模板等。
        使用常量或配置文件管理模板,便于统一修改和维护。
        模板化可以确保整个项目中日期格式的一致性。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // 日期格式化模板常量
        const (
            // API相关模板
            APIDateTime     = "Y-m-d H:i:s"
            APIDate         = "Y-m-d"
            APITime         = "H:i:s"

            // 显示相关模板
            DisplayDateTime = "Y年m月d日 H时i分"
            DisplayDate     = "Y年m月d日"
            DisplayTime     = "H时i分"

            // 文件名相关模板
            FileDateTime    = "Ymd_His"
            FileDate        = "Ymd"

            // 日志相关模板
            LogDateTime     = "Y-m-d H:i:s.u"
            LogDate         = "Y-m-d"

            // 报表相关模板
            ReportMonth     = "Y年m月"
            ReportWeek      = "Y年第W周"
            ReportDate      = "m月d日"
        )

        func main() {
            now := carbon.Now()

            // 使用API模板
            fmt.Println("=== API格式 ===")
            fmt.Println("完整:", now.Format(APIDateTime))
            fmt.Println("日期:", now.Format(APIDate))
            fmt.Println("时间:", now.Format(APITime))

            // 使用显示模板
            fmt.Println("\n=== 显示格式 ===")
            fmt.Println("完整:", now.Format(DisplayDateTime))
            fmt.Println("日期:", now.Format(DisplayDate))
            fmt.Println("时间:", now.Format(DisplayTime))

            // 使用文件名模板
            fmt.Println("\n=== 文件名格式 ===")
            backupFile := fmt.Sprintf("backup_%s.sql", now.Format(FileDateTime))
            dataFile := fmt.Sprintf("data_%s.csv", now.Format(FileDate))
            fmt.Println(backupFile)
            fmt.Println(dataFile)

            // 使用日志模板
            fmt.Println("\n=== 日志格式 ===")
            logEntry := fmt.Sprintf("[%s] Application started", now.Format(LogDateTime))
            fmt.Println(logEntry)

            // 使用报表模板
            fmt.Println("\n=== 报表格式 ===")
            fmt.Printf("%s销售报表\n", now.Format(ReportMonth))
            fmt.Printf("%s工作总结\n", now.Format(ReportWeek))
            fmt.Printf("%s考勤记录\n", now.Format(ReportDate))

            // 实用场景:格式化函数封装
            fmt.Println("\n=== 封装函数示例 ===")
            fmt.Println("API格式:", FormatForAPI(now))
            fmt.Println("显示格式:", FormatForDisplay(now))
            fmt.Println("日志格式:", FormatForLog(now))
        }

        // FormatForAPI 格式化为API格式
        func FormatForAPI(c carbon.Carbon) string {
            return c.Format(APIDateTime)
        }

        // FormatForDisplay 格式化为显示格式
        func FormatForDisplay(c carbon.Carbon) string {
            return c.Format(DisplayDateTime)
        }

        // FormatForLog 格式化为日志格式
        func FormatForLog(c carbon.Carbon) string {
            return c.Format(LogDateTime)
        }
        ---

4.3 多语言支持

01.设置语言环境
    a.说明
        Carbon支持全球30多种语言的本地化显示。
        通过SetLocale()方法设置语言环境,影响星期、月份等的显示。
        常用语言代码:zh-CN(简体中文) en(英语) ja(日语) ko(韩语)等。
        语言设置只影响当前Carbon实例,不会影响全局。
        多语言支持使Carbon适合国际化应用开发。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 中文环境
            zhCN := now.SetLocale("zh-CN")
            fmt.Println("=== 中文 ===")
            fmt.Println("星期:", zhCN.ToWeekString())
            fmt.Println("月份:", zhCN.ToMonthString())
            fmt.Println("短星期:", zhCN.ToShortWeekString())
            fmt.Println("短月份:", zhCN.ToShortMonthString())

            // 英文环境
            en := now.SetLocale("en")
            fmt.Println("\n=== English ===")
            fmt.Println("Week:", en.ToWeekString())
            fmt.Println("Month:", en.ToMonthString())
            fmt.Println("Short Week:", en.ToShortWeekString())
            fmt.Println("Short Month:", en.ToShortMonthString())

            // 日文环境
            ja := now.SetLocale("ja")
            fmt.Println("\n=== 日本語 ===")
            fmt.Println("曜日:", ja.ToWeekString())
            fmt.Println("月:", ja.ToMonthString())

            // 韩文环境
            ko := now.SetLocale("ko")
            fmt.Println("\n=== 한국어 ===")
            fmt.Println("요일:", ko.ToWeekString())
            fmt.Println("월:", ko.ToMonthString())

            // 法文环境
            fr := now.SetLocale("fr")
            fmt.Println("\n=== Français ===")
            fmt.Println("Semaine:", fr.ToWeekString())
            fmt.Println("Mois:", fr.ToMonthString())

            // 德文环境
            de := now.SetLocale("de")
            fmt.Println("\n=== Deutsch ===")
            fmt.Println("Wochentag:", de.ToWeekString())
            fmt.Println("Monat:", de.ToMonthString())

            // 西班牙文环境
            es := now.SetLocale("es")
            fmt.Println("\n=== Español ===")
            fmt.Println("Día:", es.ToWeekString())
            fmt.Println("Mes:", es.ToMonthString())

            // 实用场景:多语言日历
            fmt.Println("\n=== 多语言日历 ===")
            languages := map[string]string{
                "zh-CN": "中文",
                "en":    "English",
                "ja":    "日本語",
                "ko":    "한국어",
            }

            for code, name := range languages {
                localized := now.SetLocale(code)
                fmt.Printf("%s: %s %s\n",
                    name,
                    localized.ToDateString(),
                    localized.ToWeekString())
            }
        }
        ---

02.相对时间的多语言
    a.说明
        DiffForHumans()方法支持多语言的人性化时间描述。
        不同语言的相对时间表达方式各有特色。
        适合在界面上显示评论时间、最后登录等相对时间信息。
        多语言相对时间让应用更符合用户的语言习惯。
        结合语言设置可以实现完全本地化的时间显示。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 不同时间点
            times := []carbon.Carbon{
                now.SubSeconds(30),
                now.SubMinutes(5),
                now.SubHours(2),
                now.SubDays(1),
                now.SubWeeks(1),
                now.SubMonths(1),
            }

            // 中文相对时间
            fmt.Println("=== 中文相对时间 ===")
            for _, t := range times {
                zhCN := t.SetLocale("zh-CN")
                fmt.Println(zhCN.DiffForHumans())
            }

            // 英文相对时间
            fmt.Println("\n=== English Relative Time ===")
            for _, t := range times {
                en := t.SetLocale("en")
                fmt.Println(en.DiffForHumans())
            }

            // 日文相对时间
            fmt.Println("\n=== 日本語相対時間 ===")
            for _, t := range times {
                ja := t.SetLocale("ja")
                fmt.Println(ja.DiffForHumans())
            }

            // 实用场景:评论时间显示
            fmt.Println("\n=== 多语言评论时间 ===")
            commentTime := now.SubHours(3)

            fmt.Println("中文:", commentTime.SetLocale("zh-CN").DiffForHumans())
            fmt.Println("English:", commentTime.SetLocale("en").DiffForHumans())
            fmt.Println("日本語:", commentTime.SetLocale("ja").DiffForHumans())
            fmt.Println("한국어:", commentTime.SetLocale("ko").DiffForHumans())
        }
        ---

03.完整的本地化应用
    a.说明
        实际应用中需要根据用户设置或浏览器语言动态切换。
        可以封装语言设置逻辑,统一管理所有时间的本地化。
        建议在中间件或工具函数中集中处理语言设置。
        配合i18n库可以实现完整的国际化方案。
        多语言支持是现代Web应用的重要特性。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // UserLocale 用户语言设置
        type UserLocale struct {
            Lang string
        }

        // FormatDateTime 根据用户语言格式化时间
        func (u *UserLocale) FormatDateTime(c carbon.Carbon) string {
            localized := c.SetLocale(u.Lang)
            return localized.Format("Y-m-d H:i:s")
        }

        // FormatDate 根据用户语言格式化日期
        func (u *UserLocale) FormatDate(c carbon.Carbon) string {
            localized := c.SetLocale(u.Lang)
            return fmt.Sprintf("%s %s",
                localized.ToDateString(),
                localized.ToWeekString())
        }

        // FormatRelative 根据用户语言格式化相对时间
        func (u *UserLocale) FormatRelative(c carbon.Carbon) string {
            localized := c.SetLocale(u.Lang)
            return localized.DiffForHumans()
        }

        func main() {
            now := carbon.Now()

            // 模拟不同用户的语言设置
            users := []UserLocale{
                {Lang: "zh-CN"},
                {Lang: "en"},
                {Lang: "ja"},
                {Lang: "ko"},
            }

            fmt.Println("=== 用户自定义语言显示 ===")
            for _, user := range users {
                fmt.Printf("\n语言: %s\n", user.Lang)
                fmt.Println("日期:", user.FormatDate(now))
                fmt.Println("时间:", user.FormatDateTime(now))
                fmt.Println("相对:", user.FormatRelative(now.SubHours(2)))
            }

            // 实用场景:Web应用响应
            fmt.Println("\n=== Web响应示例 ===")
            type Article struct {
                Title     string
                CreatedAt carbon.Carbon
            }

            article := Article{
                Title:     "Go语言教程",
                CreatedAt: now.SubDays(3),
            }

            // 根据请求头的Accept-Language返回
            userLang := "zh-CN"
            locale := UserLocale{Lang: userLang}

            fmt.Printf("标题: %s\n", article.Title)
            fmt.Printf("发布时间: %s\n", locale.FormatDate(article.CreatedAt))
            fmt.Printf("发布于: %s\n", locale.FormatRelative(article.CreatedAt))
        }
        ---

4.4 常用格式化

01.数据库常用格式
    a.说明
        数据库中的时间字段通常使用标准格式存储。
        MySQL常用DATETIME格式,PostgreSQL支持多种时间格式。
        Carbon提供了便捷的方法输出数据库兼容格式。
        ToDateTimeString()适合存储到DATETIME字段。
        Timestamp()适合存储Unix时间戳。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // MySQL DATETIME格式
            fmt.Println("=== MySQL格式 ===")
            fmt.Println("DATETIME:", now.ToDateTimeString())       // 2024-01-15 10:30:00
            fmt.Println("DATE:", now.ToDateString())               // 2024-01-15
            fmt.Println("TIME:", now.ToTimeString())               // 10:30:00
            fmt.Println("TIMESTAMP:", now.Timestamp())             // 1705287000

            // PostgreSQL格式
            fmt.Println("\n=== PostgreSQL格式 ===")
            fmt.Println("TIMESTAMP:", now.ToDateTimeString())
            fmt.Println("TIMESTAMPTZ:", now.ToIso8601String())
            fmt.Println("DATE:", now.ToDateString())
            fmt.Println("TIME:", now.ToTimeString())

            // SQLite格式
            fmt.Println("\n=== SQLite格式 ===")
            fmt.Println("DATETIME:", now.ToDateTimeString())
            fmt.Println("INTEGER:", now.Timestamp())

            // 实用场景:SQL插入语句
            fmt.Println("\n=== SQL示例 ===")
            sql := fmt.Sprintf(
                "INSERT INTO users (name, created_at) VALUES ('%s', '%s')",
                "张三",
                now.ToDateTimeString(),
            )
            fmt.Println(sql)

            // 实用场景:SQL查询条件
            start := carbon.Now().StartOfDay()
            end := carbon.Now().EndOfDay()
            querySql := fmt.Sprintf(
                "SELECT * FROM orders WHERE created_at >= '%s' AND created_at <= '%s'",
                start.ToDateTimeString(),
                end.ToDateTimeString(),
            )
            fmt.Println("\n", querySql)
        }
        ---

02.API接口常用格式
    a.说明
        API接口通常使用ISO8601或RFC3339标准格式。
        这些格式包含完整的时区信息,适合跨时区数据传输。
        JSON序列化时推荐使用ISO8601格式。
        时间戳也是常用的API响应格式,简洁且易于处理。
        根据API文档规范选择合适的格式。
    b.代码示例
        ---
        package main

        import (
            "encoding/json"
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // RESTful API常用格式
            fmt.Println("=== RESTful API ===")
            fmt.Println("ISO8601:", now.ToIso8601String())
            fmt.Println("RFC3339:", now.ToRfc3339String())
            fmt.Println("Unix时间戳:", now.Timestamp())
            fmt.Println("毫秒时间戳:", now.TimestampMilli())

            // JSON响应示例
            fmt.Println("\n=== JSON响应 ===")
            type APIResponse struct {
                Code      int    `json:"code"`
                Message   string `json:"message"`
                Data      interface{} `json:"data"`
                Timestamp int64  `json:"timestamp"`
                DateTime  string `json:"datetime"`
            }

            resp := APIResponse{
                Code:      200,
                Message:   "Success",
                Data:      map[string]string{"user": "张三"},
                Timestamp: now.Timestamp(),
                DateTime:  now.ToIso8601String(),
            }

            jsonData, _ := json.MarshalIndent(resp, "", "  ")
            fmt.Println(string(jsonData))

            // GraphQL时间格式
            fmt.Println("\n=== GraphQL ===")
            fmt.Println("DateTime:", now.ToRfc3339String())
            fmt.Println("Date:", now.ToDateString())

            // 实用场景:API请求日志
            fmt.Println("\n=== API日志 ===")
            logEntry := fmt.Sprintf(
                "[%s] GET /api/users - Status: 200 - Duration: 45ms",
                now.ToIso8601String(),
            )
            fmt.Println(logEntry)
        }
        ---

03.日志文件常用格式
    a.说明
        日志记录需要精确的时间戳,通常包含毫秒或微秒。
        标准日志格式便于后续的日志分析和检索。
        可以根据日志级别和用途选择不同的时间格式。
        建议在日志中使用固定格式,便于日志解析工具处理。
        时区信息在分布式系统日志中尤为重要。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 标准日志格式
            fmt.Println("=== 标准日志格式 ===")
            fmt.Println(now.Format("Y-m-d H:i:s"))              // 2024-01-15 10:30:00
            fmt.Println(now.Format("Y-m-d H:i:s.u"))            // 2024-01-15 10:30:00.123456

            // Apache/Nginx日志格式
            fmt.Println("\n=== Web服务器日志 ===")
            fmt.Println("Common:", now.Format("d/M/Y:H:i:s O")) // 15/Jan/2024:10:30:00 +0800
            fmt.Println("ISO8601:", now.ToIso8601String())      // 2024-01-15T10:30:00+08:00

            // 应用日志格式
            fmt.Println("\n=== 应用日志 ===")
            logFormats := map[string]string{
                "INFO":  fmt.Sprintf("[%s] INFO: Application started", now.Format("Y-m-d H:i:s")),
                "DEBUG": fmt.Sprintf("[%s] DEBUG: Query executed in 45ms", now.Format("Y-m-d H:i:s.u")),
                "ERROR": fmt.Sprintf("[%s] ERROR: Connection timeout", now.Format("Y-m-d H:i:s.u")),
                "WARN":  fmt.Sprintf("[%s] WARN: High memory usage", now.Format("Y-m-d H:i:s")),
            }

            for level, msg := range logFormats {
                fmt.Println(msg)
            }

            // 文件名格式
            fmt.Println("\n=== 日志文件名 ===")
            fmt.Println("按天:", fmt.Sprintf("app_%s.log", now.Format("Y-m-d")))
            fmt.Println("按小时:", fmt.Sprintf("app_%s.log", now.Format("Y-m-d_H")))
            fmt.Println("精确:", fmt.Sprintf("backup_%s.log", now.Format("Ymd_His")))

            // 实用场景:结构化日志
            fmt.Println("\n=== 结构化日志JSON ===")
            type LogEntry struct {
                Timestamp  int64  `json:"timestamp"`
                DateTime   string `json:"datetime"`
                Level      string `json:"level"`
                Message    string `json:"message"`
                Service    string `json:"service"`
            }

            entry := LogEntry{
                Timestamp: now.Timestamp(),
                DateTime:  now.ToIso8601String(),
                Level:     "INFO",
                Message:   "Request processed successfully",
                Service:   "api-server",
            }

            fmt.Printf("{\n")
            fmt.Printf("  \"timestamp\": %d,\n", entry.Timestamp)
            fmt.Printf("  \"datetime\": \"%s\",\n", entry.DateTime)
            fmt.Printf("  \"level\": \"%s\",\n", entry.Level)
            fmt.Printf("  \"message\": \"%s\",\n", entry.Message)
            fmt.Printf("  \"service\": \"%s\"\n", entry.Service)
            fmt.Printf("}\n")
        }
        ---

4.5 链式调用

01.链式操作基础
    a.说明
        Carbon所有方法都返回新的Carbon实例,支持流畅的链式调用。
        链式调用可以在一行代码中完成多个操作,代码更简洁。
        每个操作都是独立的,不会影响原始Carbon对象。
        链式调用适合处理复杂的时间转换和格式化逻辑。
        注意链式调用中的错误处理,任一环节出错都会传递到最后。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 基础链式调用
            result1 := carbon.Now().
                AddDays(7).
                StartOfDay().
                ToDateTimeString()
            fmt.Println("7天后的凌晨:", result1)

            // 复杂链式调用
            result2 := carbon.Parse("2024-01-15").
                AddMonths(3).
                EndOfMonth().
                SubDays(1).
                ToDateString()
            fmt.Println("3个月后的月末前一天:", result2)

            // 时区转换链式调用
            result3 := carbon.Now().
                SetTimezone("America/New_York").
                AddHours(12).
                SetTimezone("Asia/Tokyo").
                ToDateTimeString()
            fmt.Println("纽约时间+12小时转东京:", result3)

            // 格式化链式调用
            result4 := carbon.Parse("2024-01-15 10:30:00").
                AddWeek().
                SetLocale("zh-CN").
                Format("Y年m月d日 l")
            fmt.Println("一周后(中文):", result4)

            // 多步骤时间计算
            result5 := carbon.Now().
                StartOfMonth().      // 本月1号
                AddMonths(1).        // 下月1号
                SubDay().            // 本月最后一天
                ToDateString()
            fmt.Println("本月最后一天:", result5)

            // 工作日计算链式调用
            result6 := carbon.Now().
                AddWorkdays(10).
                ToDateString()
            fmt.Println("10个工作日后:", result6)

            // 错误处理
            invalid := carbon.Parse("invalid").
                AddDay().
                ToDateString()
            if invalid == "" {
                fmt.Println("链式调用中存在错误")
            }
        }
        ---

02.链式调用最佳实践
    a.说明
        合理使用链式调用可以提高代码可读性和维护性。
        建议按逻辑分组进行链式调用,避免过长的调用链。
        复杂逻辑可以拆分为多个链式调用,每个处理一个方面。
        在链式调用前后添加注释,说明业务逻辑。
        注意性能,避免不必要的中间操作。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 好的实践:分步骤的链式调用
            fmt.Println("=== 好的实践 ===")

            // 步骤1:获取下月第一天
            nextMonthFirst := carbon.Now().
                AddMonth().
                StartOfMonth()
            fmt.Println("下月第一天:", nextMonthFirst.ToDateString())

            // 步骤2:转换时区并格式化
            formatted := nextMonthFirst.
                SetTimezone("UTC").
                SetLocale("zh-CN").
                Format("Y年m月d日 H时i分")
            fmt.Println("格式化:", formatted)

            // 实用场景:账单周期计算
            fmt.Println("\n=== 账单周期 ===")
            // 当前账单周期:本月1号到本月最后一天
            currentPeriodStart := carbon.Now().StartOfMonth()
            currentPeriodEnd := carbon.Now().EndOfMonth()

            fmt.Printf("当前周期: %s ~ %s\n",
                currentPeriodStart.ToDateString(),
                currentPeriodEnd.ToDateString())

            // 下个账单周期
            nextPeriodStart := carbon.Now().
                AddMonth().
                StartOfMonth()

            nextPeriodEnd := carbon.Now().
                AddMonth().
                EndOfMonth()

            fmt.Printf("下个周期: %s ~ %s\n",
                nextPeriodStart.ToDateString(),
                nextPeriodEnd.ToDateString())

            // 实用场景:会员到期提醒
            fmt.Println("\n=== 会员到期提醒 ===")
            membershipStart := carbon.Parse("2024-01-01")
            membershipEnd := membershipStart.
                AddYear().    // 会员期1年
                SubDay()      // 到期日前一天

            fmt.Println("会员开始:", membershipStart.ToDateString())
            fmt.Println("会员到期:", membershipEnd.ToDateString())

            // 提醒时间:到期前7天
            reminderDate := membershipEnd.
                SubDays(7).
                StartOfDay()
            fmt.Println("提醒日期:", reminderDate.ToDateString())

            // 实用场景:报表日期范围
            fmt.Println("\n=== 季度报表 ===")
            quarterStart := carbon.Now().
                StartOfQuarter().
                ToDateString()

            quarterEnd := carbon.Now().
                EndOfQuarter().
                ToDateString()

            fmt.Printf("Q%d报表: %s ~ %s\n",
                carbon.Now().Quarter(),
                quarterStart,
                quarterEnd)
        }
        ---

03.函数式编程风格
    a.说明
        链式调用配合函数式编程可以实现更优雅的代码。
        可以将常用的链式操作封装为辅助函数。
        函数返回Carbon实例,支持继续链式调用。
        这种风格适合处理复杂的业务逻辑。
        提高了代码的复用性和可测试性。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // GetNextBusinessDay 获取下一个工作日
        func GetNextBusinessDay(c carbon.Carbon) carbon.Carbon {
            next := c.AddDay()
            for next.IsWeekend() {
                next = next.AddDay()
            }
            return next
        }

        // GetMonthRange 获取指定月份的范围
        func GetMonthRange(c carbon.Carbon) (carbon.Carbon, carbon.Carbon) {
            start := c.StartOfMonth()
            end := c.EndOfMonth()
            return start, end
        }

        // FormatChinese 格式化为中文显示
        func FormatChinese(c carbon.Carbon) string {
            return c.SetLocale("zh-CN").Format("Y年m月d日 l")
        }

        // ToUTC 转换为UTC时间
        func ToUTC(c carbon.Carbon) carbon.Carbon {
            return c.SetTimezone("UTC")
        }

        func main() {
            now := carbon.Now()

            // 使用辅助函数的链式调用
            fmt.Println("=== 函数式风格 ===")

            // 下一个工作日(UTC时区,中文显示)
            result := FormatChinese(ToUTC(GetNextBusinessDay(now)))
            fmt.Println("下一个工作日:", result)

            // 本月范围
            start, end := GetMonthRange(now)
            fmt.Printf("本月: %s ~ %s\n",
                FormatChinese(start),
                FormatChinese(end))

            // 实用场景:项目里程碑计算
            fmt.Println("\n=== 项目里程碑 ===")
            projectStart := carbon.Parse("2024-01-01")

            milestones := map[string]carbon.Carbon{
                "需求分析完成":  GetNextBusinessDay(projectStart.AddWeeks(2)),
                "设计评审完成":  GetNextBusinessDay(projectStart.AddWeeks(4)),
                "开发完成":    GetNextBusinessDay(projectStart.AddWeeks(12)),
                "测试完成":    GetNextBusinessDay(projectStart.AddWeeks(14)),
                "项目上线":    GetNextBusinessDay(projectStart.AddWeeks(16)),
            }

            for milestone, date := range milestones {
                fmt.Printf("%s: %s\n", milestone, FormatChinese(date))
            }

            // 实用场景:动态时间计算
            fmt.Println("\n=== 动态计算示例 ===")
            type TimeCalculator struct {
                base carbon.Carbon
            }

            calc := TimeCalculator{base: carbon.Now()}

            // 方法链式调用
            result2 := calc.base.
                AddMonths(3).
                StartOfMonth().
                ToDateString()

            fmt.Println("3个月后的月初:", result2)
        }
        ---

5 高级特性

5.1 时区处理

01.时区设置与转换
    a.说明
        Carbon支持全球所有IANA时区数据库中的时区。
        SetTimezone()方法可以转换时区,保持同一时刻的不同地区表示。
        时区转换在国际化应用、跨地区协作等场景中至关重要。
        建议在数据库中存储UTC时间,显示时再转换为用户时区。
        Carbon会自动处理夏令时等复杂的时区规则。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 获取当前时间(本地时区)
            now := carbon.Now()
            fmt.Println("本地时间:", now.ToDateTimeString())
            fmt.Println("本地时区:", now.Timezone())

            // 转换到不同时区
            fmt.Println("\n=== 世界主要城市时间 ===")
            cities := map[string]string{
                "纽约":   "America/New_York",
                "伦敦":   "Europe/London",
                "巴黎":   "Europe/Paris",
                "东京":   "Asia/Tokyo",
                "悉尼":   "Australia/Sydney",
                "迪拜":   "Asia/Dubai",
            }

            for city, timezone := range cities {
                cityTime := now.SetTimezone(timezone)
                fmt.Printf("%s: %s (%s)\n",
                    city,
                    cityTime.ToDateTimeString(),
                    cityTime.Timezone())
            }

            // UTC时间
            utc := now.SetTimezone("UTC")
            fmt.Println("\nUTC时间:", utc.ToDateTimeString())

            // 时区缩写
            fmt.Println("\n=== 常用时区 ===")
            fmt.Println("PRC(北京):", now.SetTimezone(carbon.PRC).ToDateTimeString())
            fmt.Println("UTC:", now.SetTimezone(carbon.UTC).ToDateTimeString())
            fmt.Println("Local:", now.SetTimezone(carbon.Local).ToDateTimeString())

            // 实用场景:跨时区会议时间
            fmt.Println("\n=== 跨时区会议 ===")
            meetingTime := carbon.Parse("2024-01-15 14:00:00").
                SetTimezone("Asia/Shanghai")

            fmt.Println("北京时间:", meetingTime.ToDateTimeString())
            fmt.Println("纽约时间:", meetingTime.SetTimezone("America/New_York").ToDateTimeString())
            fmt.Println("伦敦时间:", meetingTime.SetTimezone("Europe/London").ToDateTimeString())
        }
        ---

02.时区偏移量
    a.说明
        时区偏移量表示与UTC的时差,以秒为单位。
        正值表示东时区,负值表示西时区。
        Offset()方法返回当前时区的偏移秒数。
        OffsetHours()返回小时数,更直观。
        了解时区偏移有助于手动处理时区相关计算。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 获取时区偏移量
            fmt.Println("=== 时区偏移量 ===")
            offset := now.Offset()
            hours := now.OffsetHours()

            fmt.Printf("当前时区: %s\n", now.Timezone())
            fmt.Printf("偏移秒数: %d秒\n", offset)
            fmt.Printf("偏移小时: %d小时\n", hours)

            // 不同时区的偏移量
            fmt.Println("\n=== 各时区偏移量 ===")
            timezones := []string{
                "Asia/Shanghai",     // UTC+8
                "America/New_York",  // UTC-5
                "Europe/London",     // UTC+0
                "Asia/Tokyo",        // UTC+9
                "Australia/Sydney",  // UTC+10
            }

            for _, tz := range timezones {
                t := now.SetTimezone(tz)
                fmt.Printf("%-20s UTC%+d (%d秒)\n",
                    tz,
                    t.OffsetHours(),
                    t.Offset())
            }

            // 实用场景:时区感知的时间戳
            fmt.Println("\n=== 时区与时间戳 ===")
            shanghai := carbon.Parse("2024-01-15 12:00:00").
                SetTimezone("Asia/Shanghai")
            newYork := carbon.Parse("2024-01-15 12:00:00").
                SetTimezone("America/New_York")

            fmt.Println("上海12点:", shanghai.ToDateTimeString())
            fmt.Println("纽约12点:", newYork.ToDateTimeString())
            fmt.Println("上海时间戳:", shanghai.Timestamp())
            fmt.Println("纽约时间戳:", newYork.Timestamp())
            fmt.Println("时间戳差值:", shanghai.Timestamp()-newYork.Timestamp(), "秒")
        }
        ---

03.夏令时处理
    a.说明
        夏令时(DST)是部分国家和地区实行的时间调整制度。
        Carbon自动处理夏令时的时间变化,无需手动干预。
        IsDST()方法可以判断当前时间是否处于夏令时。
        在涉及夏令时的时区中,时间加减可能出现非连续跳跃。
        了解夏令时机制有助于避免时区相关的bug。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 夏令时判断
            fmt.Println("=== 夏令时判断 ===")

            // 美国夏令时示例(3月第二个周日开始,11月第一个周日结束)
            summer := carbon.Parse("2024-07-15 12:00:00").
                SetTimezone("America/New_York")
            winter := carbon.Parse("2024-01-15 12:00:00").
                SetTimezone("America/New_York")

            fmt.Printf("夏季(%s): %v\n",
                summer.ToDateString(),
                summer.IsDST())
            fmt.Printf("冬季(%s): %v\n",
                winter.ToDateString(),
                winter.IsDST())

            // 时区偏移在夏令时的变化
            fmt.Println("\n=== 夏令时偏移变化 ===")
            fmt.Printf("夏季偏移: UTC%+d\n", summer.OffsetHours())
            fmt.Printf("冬季偏移: UTC%+d\n", winter.OffsetHours())

            // 中国不实行夏令时
            shanghaiSummer := carbon.Parse("2024-07-15 12:00:00").
                SetTimezone("Asia/Shanghai")
            shanghaiWinter := carbon.Parse("2024-01-15 12:00:00").
                SetTimezone("Asia/Shanghai")

            fmt.Println("\n=== 中国时区(无夏令时) ===")
            fmt.Printf("夏季: %v, UTC%+d\n",
                shanghaiSummer.IsDST(),
                shanghaiSummer.OffsetHours())
            fmt.Printf("冬季: %v, UTC%+d\n",
                shanghaiWinter.IsDST(),
                shanghaiWinter.OffsetHours())

            // 实用场景:夏令时切换时的时间计算
            fmt.Println("\n=== 夏令时切换 ===")
            // 2024年美国夏令时开始日期大约在3月10日
            beforeDST := carbon.Parse("2024-03-10 01:00:00").
                SetTimezone("America/New_York")
            afterDST := beforeDST.AddHours(2)

            fmt.Println("切换前:", beforeDST.ToDateTimeString(), "DST:", beforeDST.IsDST())
            fmt.Println("切换后:", afterDST.ToDateTimeString(), "DST:", afterDST.IsDST())
        }
        ---

5.2 星期处理

01.星期相关方法
    a.说明
        Carbon提供了丰富的星期处理方法,包括获取、判断和计算。
        DayOfWeek()返回星期几的数字(0=周日,6=周六)。
        WeekOfMonth()返回当月的第几周,WeekOfYear()返回当年的第几周。
        IsXxx()系列方法可以判断是否为特定的星期几。
        星期相关功能在排班、报表统计等场景中非常实用。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Parse("2024-01-15") // 2024年1月15日是周一

            // 获取星期信息
            fmt.Println("=== 星期信息 ===")
            fmt.Println("日期:", now.ToDateString())
            fmt.Println("星期几:", now.DayOfWeek())           // 1(周一)
            fmt.Println("星期名称:", now.ToWeekString())       // Monday
            fmt.Println("短名称:", now.ToShortWeekString())   // Mon

            // 当月第几周
            fmt.Println("当月第几周:", now.WeekOfMonth())     // 3

            // 当年第几周
            fmt.Println("当年第几周:", now.WeekOfYear())      // 3

            // 判断是否为特定星期几
            fmt.Println("\n=== 星期判断 ===")
            fmt.Println("是否周一:", now.IsMonday())         // true
            fmt.Println("是否周二:", now.IsTuesday())        // false
            fmt.Println("是否周三:", now.IsWednesday())      // false
            fmt.Println("是否周四:", now.IsThursday())       // false
            fmt.Println("是否周五:", now.IsFriday())         // false
            fmt.Println("是否周六:", now.IsSaturday())       // false
            fmt.Println("是否周日:", now.IsSunday())         // false

            // 工作日和周末
            fmt.Println("\n=== 工作日判断 ===")
            fmt.Println("是否工作日:", now.IsWeekday())      // true
            fmt.Println("是否周末:", now.IsWeekend())        // false

            // 遍历一周
            fmt.Println("\n=== 本周每天 ===")
            weekStart := now.StartOfWeek()
            for i := 0; i < 7; i++ {
                day := weekStart.AddDays(i)
                weekday := "工作日"
                if day.IsWeekend() {
                    weekday = "周末"
                }
                fmt.Printf("%s %s (%s)\n",
                    day.ToDateString(),
                    day.ToWeekString(),
                    weekday)
            }

            // 实用场景:查找本月所有周末
            fmt.Println("\n=== 本月所有周末 ===")
            monthStart := now.StartOfMonth()
            daysInMonth := monthStart.DaysInMonth()

            for i := 0; i < daysInMonth; i++ {
                day := monthStart.AddDays(i)
                if day.IsWeekend() {
                    fmt.Println(day.ToDateString(), day.ToWeekString())
                }
            }
        }
        ---

02.周的开始和结束
    a.说明
        StartOfWeek()和EndOfWeek()获取一周的开始和结束时间。
        默认周一为一周的开始,符合ISO8601标准。
        周的概念在报表统计、周期性任务等场景中广泛使用。
        可以配合WeekOfYear()实现按周的数据聚合。
        了解周的边界对于正确处理跨周业务逻辑很重要。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Parse("2024-01-15") // 周一

            // 本周范围
            fmt.Println("=== 本周范围 ===")
            weekStart := now.StartOfWeek()
            weekEnd := now.EndOfWeek()

            fmt.Println("本周开始:", weekStart.ToDateTimeString())
            fmt.Println("本周结束:", weekEnd.ToDateTimeString())
            fmt.Println("本周天数:", weekEnd.DiffInDays(weekStart)+1)

            // 上周范围
            fmt.Println("\n=== 上周范围 ===")
            lastWeekStart := now.SubWeek().StartOfWeek()
            lastWeekEnd := now.SubWeek().EndOfWeek()

            fmt.Println("上周开始:", lastWeekStart.ToDateString())
            fmt.Println("上周结束:", lastWeekEnd.ToDateString())

            // 下周范围
            fmt.Println("\n=== 下周范围 ===")
            nextWeekStart := now.AddWeek().StartOfWeek()
            nextWeekEnd := now.AddWeek().EndOfWeek()

            fmt.Println("下周开始:", nextWeekStart.ToDateString())
            fmt.Println("下周结束:", nextWeekEnd.ToDateString())

            // 实用场景:周报日期范围
            fmt.Println("\n=== 周报示例 ===")
            fmt.Printf("第%d周周报\n", now.WeekOfYear())
            fmt.Printf("统计周期: %s 至 %s\n",
                weekStart.ToDateString(),
                weekEnd.ToDateString())

            // 实用场景:本周工作日数量
            fmt.Println("\n=== 本周工作日 ===")
            workdayCount := 0
            current := weekStart

            for current.Lte(weekEnd) {
                if current.IsWeekday() {
                    workdayCount++
                    fmt.Printf("%s %s\n",
                        current.ToDateString(),
                        current.ToWeekString())
                }
                current = current.AddDay()
            }
            fmt.Printf("本周共有 %d 个工作日\n", workdayCount)
        }
        ---

03.ISO周和周年
    a.说明
        ISO8601标准定义了ISO周的概念,用于标准化的周数计算。
        ISO周的第一周必须包含当年的第一个周四。
        IsoWeek()返回ISO周数,IsoWeeksOfYear()返回当年的ISO周总数。
        ISO周在国际化项目和标准化报表中广泛使用。
        了解ISO周有助于正确处理跨年周等边界情况。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 年初日期
            newYear := carbon.Parse("2024-01-01")

            fmt.Println("=== ISO周信息 ===")
            fmt.Println("日期:", newYear.ToDateString())
            fmt.Println("星期几:", newYear.ToWeekString())
            fmt.Println("ISO周数:", newYear.WeekOfYear())

            // 年末日期
            yearEnd := carbon.Parse("2024-12-31")
            fmt.Println("\n日期:", yearEnd.ToDateString())
            fmt.Println("星期几:", yearEnd.ToWeekString())
            fmt.Println("ISO周数:", yearEnd.WeekOfYear())
            fmt.Println("全年ISO周数:", yearEnd.WeeksOfYear())

            // 遍历全年的周
            fmt.Println("\n=== 2024年各周起止日期 ===")
            year := carbon.Parse("2024-01-01")
            weekCount := year.WeeksOfYear()

            // 只显示前4周和后4周
            fmt.Println("前4周:")
            for week := 1; week <= 4; week++ {
                // 找到该周的第一天
                current := year
                for current.WeekOfYear() != week {
                    current = current.AddDay()
                }
                weekStart := current.StartOfWeek()
                weekEnd := current.EndOfWeek()

                fmt.Printf("第%02d周: %s ~ %s\n",
                    week,
                    weekStart.ToDateString(),
                    weekEnd.ToDateString())
            }

            fmt.Println("...")
            fmt.Println("后4周:")
            for week := weekCount - 3; week <= weekCount; week++ {
                current := carbon.Parse("2024-12-31")
                for current.WeekOfYear() != week {
                    current = current.SubDay()
                }
                weekStart := current.StartOfWeek()
                weekEnd := current.EndOfWeek()

                fmt.Printf("第%02d周: %s ~ %s\n",
                    week,
                    weekStart.ToDateString(),
                    weekEnd.ToDateString())
            }

            // 实用场景:按周统计数据
            fmt.Println("\n=== 按周统计示例 ===")
            dates := []string{
                "2024-01-01",
                "2024-01-08",
                "2024-01-15",
                "2024-01-22",
            }

            weeklyData := make(map[int]int)
            for _, dateStr := range dates {
                date := carbon.Parse(dateStr)
                week := date.WeekOfYear()
                weeklyData[week]++
            }

            for week, count := range weeklyData {
                fmt.Printf("第%d周: %d条记录\n", week, count)
            }
        }
        ---

5.3 季节判断

01.季节判断方法
    a.说明
        Carbon提供了季节判断方法,可以判断当前时间属于哪个季节。
        Season()方法返回季节名称,IsSpring()等方法判断是否为特定季节。
        季节划分基于北半球的气象季节标准。
        在商业分析、季节性活动等场景中非常实用。
        可以根据业务需求自定义季节划分逻辑。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 不同月份的季节判断
            months := []string{
                "2024-01-15", // 冬季
                "2024-04-15", // 春季
                "2024-07-15", // 夏季
                "2024-10-15", // 秋季
            }

            fmt.Println("=== 季节判断 ===")
            for _, month := range months {
                date := carbon.Parse(month)
                fmt.Printf("%s: %s\n",
                    date.Format("m月"),
                    date.Season())
            }

            // 使用季节判断方法
            summer := carbon.Parse("2024-07-15")
            fmt.Println("\n=== 季节判断方法 ===")
            fmt.Println("日期:", summer.ToDateString())
            fmt.Println("是否春季:", summer.IsSpring())
            fmt.Println("是否夏季:", summer.IsSummer())
            fmt.Println("是否秋季:", summer.IsAutumn())
            fmt.Println("是否冬季:", summer.IsWinter())

            // 遍历全年,统计各季节天数
            fmt.Println("\n=== 2024年各季节天数 ===")
            seasonDays := map[string]int{
                "spring": 0,
                "summer": 0,
                "autumn": 0,
                "winter": 0,
            }

            year := carbon.Parse("2024-01-01")
            for i := 0; i < 366; i++ { // 2024是闰年
                day := year.AddDays(i)
                season := day.Season()
                seasonDays[season]++
            }

            for season, days := range seasonDays {
                fmt.Printf("%s: %d天\n", season, days)
            }

            // 实用场景:季节性商品推荐
            fmt.Println("\n=== 季节性商品推荐 ===")
            today := carbon.Now()
            season := today.Season()

            products := map[string][]string{
                "spring": {"春装", "雨伞", "防晒霜"},
                "summer": {"防晒衣", "凉鞋", "游泳装备"},
                "autumn": {"秋装", "保温杯", "风衣"},
                "winter": {"羽绒服", "暖宝宝", "加湿器"},
            }

            fmt.Printf("当前季节: %s\n", season)
            fmt.Println("推荐商品:")
            for _, product := range products[season] {
                fmt.Printf("  - %s\n", product)
            }
        }
        ---

02.季度处理
    a.说明
        Quarter()方法返回当前是第几季度(1-4)。
        StartOfQuarter()和EndOfQuarter()获取季度的开始和结束时间。
        季度在财务报表、业绩统计等商业场景中广泛使用。
        可以方便地进行季度维度的数据聚合和分析。
        季度计算在跨年场景中需要特别注意。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 获取当前季度
            now := carbon.Now()
            fmt.Println("=== 当前季度信息 ===")
            fmt.Println("当前日期:", now.ToDateString())
            fmt.Println("当前季度:", now.Quarter())
            fmt.Println("季度名称:", now.ToQuarterString())

            // 季度范围
            quarterStart := now.StartOfQuarter()
            quarterEnd := now.EndOfQuarter()
            fmt.Println("季度开始:", quarterStart.ToDateString())
            fmt.Println("季度结束:", quarterEnd.ToDateString())
            fmt.Println("季度天数:", quarterEnd.DiffInDays(quarterStart)+1)

            // 遍历全年4个季度
            fmt.Println("\n=== 2024年各季度 ===")
            year := carbon.Parse("2024-01-01")

            for q := 1; q <= 4; q++ {
                // 找到该季度的第一个月
                quarterMonth := (q-1)*3 + 1
                quarterDate := carbon.Parse(fmt.Sprintf("2024-%02d-01", quarterMonth))

                qStart := quarterDate.StartOfQuarter()
                qEnd := quarterDate.EndOfQuarter()
                days := qEnd.DiffInDays(qStart) + 1

                fmt.Printf("Q%d: %s ~ %s (%d天)\n",
                    q,
                    qStart.ToDateString(),
                    qEnd.ToDateString(),
                    days)
            }

            // 实用场景:季度报表
            fmt.Println("\n=== 季度报表示例 ===")
            currentQ := now.Quarter()
            fmt.Printf("2024年第%d季度业绩报告\n", currentQ)
            fmt.Printf("统计周期: %s 至 %s\n",
                quarterStart.ToDateString(),
                quarterEnd.ToDateString())

            // 计算已过去的季度数
            yearStart := carbon.Parse("2024-01-01")
            quartersPassed := now.DiffInQuarters(yearStart)
            fmt.Printf("年初至今已过 %d 个季度\n", quartersPassed)

            // 判断是否为季度末
            lastDayOfQuarter := now.EndOfQuarter()
            isQuarterEnd := now.ToDateString() == lastDayOfQuarter.ToDateString()
            fmt.Printf("是否季度末: %v\n", isQuarterEnd)
        }
        ---

03.自定义季节划分
    a.说明
        Carbon的默认季节划分可能不适合所有业务场景。
        可以根据实际需求自定义季节划分逻辑。
        例如根据气候、销售周期或其他业务特征划分。
        自定义季节划分需要封装独立的判断函数。
        灵活的季节划分能更好地服务于业务分析。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // CustomSeason 自定义季节类型
        type CustomSeason string

        const (
            EarlySpring CustomSeason = "早春"
            LateSpring  CustomSeason = "晚春"
            EarlySummer CustomSeason = "初夏"
            MidSummer   CustomSeason = "盛夏"
            EarlyAutumn CustomSeason = "初秋"
            LateAutumn  CustomSeason = "晚秋"
            EarlyWinter CustomSeason = "初冬"
            MidWinter   CustomSeason = "隆冬"
        )

        // GetCustomSeason 获取自定义季节(按月份细分)
        func GetCustomSeason(c carbon.Carbon) CustomSeason {
            month := c.Month()
            switch month {
            case 1:
                return MidWinter
            case 2:
                return EarlySpring
            case 3:
                return LateSpring
            case 4:
                return LateSpring
            case 5:
                return EarlySummer
            case 6:
                return MidSummer
            case 7:
                return MidSummer
            case 8:
                return EarlyAutumn
            case 9:
                return EarlyAutumn
            case 10:
                return LateAutumn
            case 11:
                return EarlyWinter
            case 12:
                return MidWinter
            default:
                return MidWinter
            }
        }

        // GetBusinessSeason 商业季节(根据销售特征)
        func GetBusinessSeason(c carbon.Carbon) string {
            month := c.Month()
            switch {
            case month == 1 || month == 2:
                return "春节季"
            case month >= 3 && month <= 5:
                return "春季促销"
            case month == 6:
                return "618购物节"
            case month >= 7 && month <= 9:
                return "暑期档"
            case month == 10:
                return "国庆季"
            case month == 11:
                return "双十一"
            case month == 12:
                return "年终促销"
            default:
                return "常规季"
            }
        }

        func main() {
            // 使用自定义季节划分
            fmt.Println("=== 自定义季节划分 ===")
            months := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}

            for _, month := range months {
                date := carbon.Parse(fmt.Sprintf("2024-%02d-15", month))
                customSeason := GetCustomSeason(date)
                businessSeason := GetBusinessSeason(date)

                fmt.Printf("%2d月: %s / %s\n",
                    month,
                    customSeason,
                    businessSeason)
            }

            // 实用场景:商品库存调整
            fmt.Println("\n=== 商品库存建议 ===")
            today := carbon.Now()
            businessSeason := GetBusinessSeason(today)

            inventory := map[string]map[string]string{
                "春节季":   {"重点": "年货、礼品", "减少": "夏季商品"},
                "春季促销":  {"重点": "春装、户外", "减少": "冬季商品"},
                "618购物节": {"重点": "电子产品、家电", "减少": "无"},
                "暑期档":   {"重点": "夏季服装、旅游用品", "减少": "春装"},
                "国庆季":   {"重点": "旅游用品、礼品", "减少": "无"},
                "双十一":   {"重点": "全品类", "减少": "无"},
                "年终促销":  {"重点": "冬季商品、年货", "减少": "夏季商品"},
            }

            fmt.Printf("当前: %s\n", businessSeason)
            if advice, ok := inventory[businessSeason]; ok {
                fmt.Printf("重点备货: %s\n", advice["重点"])
                fmt.Printf("减少库存: %s\n", advice["减少"])
            }
        }
        ---

5.4 生肖星座

01.生肖功能
    a.说明
        Carbon提供了中国传统生肖的计算功能。
        Animal()方法返回生肖名称,支持中文和英文。
        生肖是根据农历年份计算的,与公历不完全对应。
        在中国特色应用、用户画像等场景中可以增加趣味性。
        生肖功能展示了Carbon对本地化特性的支持。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 获取生肖
            now := carbon.Now()
            fmt.Println("=== 生肖查询 ===")
            fmt.Println("当前年份:", now.Year())
            fmt.Println("生肖:", now.Animal())

            // 查询不同年份的生肖
            fmt.Println("\n=== 十二生肖轮回 ===")
            baseYear := 2020
            for i := 0; i < 12; i++ {
                year := baseYear + i
                date := carbon.Parse(fmt.Sprintf("%d-01-01", year))
                fmt.Printf("%d年: %s\n", year, date.Animal())
            }

            // 根据出生日期查生肖
            fmt.Println("\n=== 根据生日查生肖 ===")
            birthdays := []string{
                "1990-05-15",
                "1995-08-20",
                "2000-03-10",
                "2010-12-25",
            }

            for _, birthday := range birthdays {
                date := carbon.Parse(birthday)
                fmt.Printf("%s 出生: %s年 属%s\n",
                    birthday,
                    date.Format("Y"),
                    date.Animal())
            }

            // 实用场景:生肖运势推荐
            fmt.Println("\n=== 今日生肖运势 ===")
            userBirthday := carbon.Parse("1990-05-15")
            userAnimal := userBirthday.Animal()

            fmt.Printf("您的生肖: %s\n", userAnimal)
            fmt.Printf("今日运势: 根据%s年运势...\n", userAnimal)

            // 生肖配对(示例)
            partnerBirthday := carbon.Parse("1995-08-20")
            partnerAnimal := partnerBirthday.Animal()

            fmt.Printf("\n=== 生肖配对 ===\n")
            fmt.Printf("您: %s\n", userAnimal)
            fmt.Printf("TA: %s\n", partnerAnimal)
        }
        ---

02.星座功能
    a.说明
        Constellation()方法返回星座名称。
        星座是根据公历出生月日计算的,共12个星座。
        每个星座都有特定的日期范围。
        在社交应用、个性化推荐等场景中广泛使用。
        星座功能可以增加应用的趣味性和用户粘性。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 获取星座
            birthday := carbon.Parse("1990-05-15")
            fmt.Println("=== 星座查询 ===")
            fmt.Println("生日:", birthday.ToDateString())
            fmt.Println("星座:", birthday.Constellation())

            // 遍历12星座的日期范围
            fmt.Println("\n=== 十二星座 ===")
            constellationDates := []string{
                "01-20", // 水瓶座
                "02-19", // 双鱼座
                "03-21", // 白羊座
                "04-20", // 金牛座
                "05-21", // 双子座
                "06-22", // 巨蟹座
                "07-23", // 狮子座
                "08-23", // 处女座
                "09-23", // 天秤座
                "10-24", // 天蝎座
                "11-23", // 射手座
                "12-22", // 摩羯座
            }

            for _, dateStr := range constellationDates {
                date := carbon.Parse("2024-" + dateStr)
                fmt.Printf("%s: %s\n",
                    date.Format("m月d日"),
                    date.Constellation())
            }

            // 查询多个生日的星座
            fmt.Println("\n=== 批量查询星座 ===")
            birthdays := []string{
                "1990-01-15",
                "1992-03-20",
                "1995-07-10",
                "2000-12-25",
            }

            for _, bd := range birthdays {
                date := carbon.Parse(bd)
                fmt.Printf("%s: %s\n",
                    date.ToDateString(),
                    date.Constellation())
            }

            // 实用场景:星座匹配度
            fmt.Println("\n=== 星座配对 ===")
            user1 := carbon.Parse("1990-05-15")
            user2 := carbon.Parse("1992-09-20")

            fmt.Printf("用户1: %s (%s)\n",
                user1.Constellation(),
                user1.ToDateString())
            fmt.Printf("用户2: %s (%s)\n",
                user2.Constellation(),
                user2.ToDateString())
            fmt.Println("配对指数: (根据星座特征计算...)")
        }
        ---

03.综合应用
    a.说明
        生肖和星座可以结合使用,提供更丰富的用户画像。
        可以根据生肖和星座推送个性化内容。
        在社交、娱乐、电商等领域有广泛应用。
        结合其他用户数据可以实现精准营销。
        注意尊重用户隐私,合理使用这些特性。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // UserProfile 用户画像
        type UserProfile struct {
            Name          string
            Birthday      carbon.Carbon
            Age           int
            Animal        string
            Constellation string
        }

        // NewUserProfile 创建用户画像
        func NewUserProfile(name, birthday string) *UserProfile {
            bd := carbon.Parse(birthday)
            age := carbon.Now().DiffInYears(bd)

            return &UserProfile{
                Name:          name,
                Birthday:      bd,
                Age:           int(age),
                Animal:        bd.Animal(),
                Constellation: bd.Constellation(),
            }
        }

        // String 格式化输出
        func (up *UserProfile) String() string {
            return fmt.Sprintf(
                "姓名: %s\n生日: %s\n年龄: %d岁\n生肖: %s\n星座: %s",
                up.Name,
                up.Birthday.ToDateString(),
                up.Age,
                up.Animal,
                up.Constellation,
            )
        }

        func main() {
            // 创建用户画像
            fmt.Println("=== 用户画像 ===")
            users := []*UserProfile{
                NewUserProfile("张三", "1990-05-15"),
                NewUserProfile("李四", "1995-09-20"),
                NewUserProfile("王五", "2000-01-10"),
            }

            for i, user := range users {
                fmt.Printf("\n用户%d:\n%s\n", i+1, user.String())
            }

            // 实用场景:生日提醒
            fmt.Println("\n=== 生日提醒 ===")
            today := carbon.Now()

            for _, user := range users {
                // 检查是否本月生日
                if user.Birthday.Month() == today.Month() {
                    fmt.Printf("%s 的生日在本月(%d月%d日)\n",
                        user.Name,
                        user.Birthday.Month(),
                        user.Birthday.Day())

                    // 计算距离生日的天数
                    thisBirthday := carbon.Parse(fmt.Sprintf(
                        "%d-%02d-%02d",
                        today.Year(),
                        user.Birthday.Month(),
                        user.Birthday.Day(),
                    ))

                    if thisBirthday.Gte(today) {
                        days := thisBirthday.DiffInDays(today)
                        fmt.Printf("  距离生日还有 %d 天\n", days)
                    }
                }
            }

            // 实用场景:星座运势推送
            fmt.Println("\n=== 每日星座运势 ===")
            for _, user := range users {
                fmt.Printf("%s(%s): 今日运势...\n",
                    user.Name,
                    user.Constellation)
            }

            // 实用场景:生肖年份特惠
            fmt.Println("\n=== 本命年优惠 ===")
            currentYearAnimal := today.Animal()
            fmt.Printf("今年是%s年\n", currentYearAnimal)

            for _, user := range users {
                if user.Animal == currentYearAnimal {
                    fmt.Printf("%s 属%s,本命年享受特别优惠!\n",
                        user.Name,
                        user.Animal)
                }
            }
        }
        ---

5.5 农历支持

01.农历日期获取
    a.说明
        Carbon提供了农历(阴历)日期的计算功能。
        Lunar()方法返回对应的农历日期信息。
        农历在中国传统节日、生日庆祝等场景中广泛使用。
        农历计算复杂,涉及闰月、节气等传统历法知识。
        Carbon封装了农历计算逻辑,开发者无需深入了解细节。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 获取当前日期的农历
            now := carbon.Now()
            fmt.Println("=== 农历查询 ===")
            fmt.Println("公历:", now.ToDateString())
            fmt.Println("农历年:", now.Lunar().Year())
            fmt.Println("农历月:", now.Lunar().Month())
            fmt.Println("农历日:", now.Lunar().Day())
            fmt.Println("是否闰月:", now.Lunar().IsLeapMonth())

            // 农历年的生肖
            fmt.Println("农历生肖:", now.Lunar().Animal())

            // 农历月份中文表示
            fmt.Println("\n=== 农历月份 ===")
            months := []string{
                "2024-01-15", "2024-02-15", "2024-03-15",
                "2024-04-15", "2024-05-15", "2024-06-15",
                "2024-07-15", "2024-08-15", "2024-09-15",
                "2024-10-15", "2024-11-15", "2024-12-15",
            }

            for _, dateStr := range months {
                date := carbon.Parse(dateStr)
                lunar := date.Lunar()
                fmt.Printf("%s: 农历%d月%d日\n",
                    date.Format("m月"),
                    lunar.Month(),
                    lunar.Day())
            }

            // 查询农历生日
            fmt.Println("\n=== 农历生日查询 ===")
            birthday := carbon.Parse("1990-05-15")
            lunarBD := birthday.Lunar()

            fmt.Println("公历生日:", birthday.ToDateString())
            fmt.Printf("农历生日: %d年%d月%d日\n",
                lunarBD.Year(),
                lunarBD.Month(),
                lunarBD.Day())
            fmt.Println("农历生肖:", lunarBD.Animal())
        }
        ---

02.传统节日判断
    a.说明
        许多中国传统节日是按农历计算的。
        可以根据农历日期判断是否为传统节日。
        常见节日包括春节、元宵、端午、中秋等。
        节日判断在节日营销、节日问候等场景中非常实用。
        可以封装节日判断逻辑,方便在项目中复用。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // ChineseHoliday 中国传统节日
        type ChineseHoliday struct {
            Name  string
            Month int
            Day   int
        }

        // 传统节日列表
        var chineseHolidays = []ChineseHoliday{
            {"春节", 1, 1},
            {"元宵节", 1, 15},
            {"龙抬头", 2, 2},
            {"端午节", 5, 5},
            {"七夕节", 7, 7},
            {"中元节", 7, 15},
            {"中秋节", 8, 15},
            {"重阳节", 9, 9},
            {"腊八节", 12, 8},
            {"小年", 12, 23},
            {"除夕", 12, 30},
        }

        // GetChineseHoliday 获取传统节日
        func GetChineseHoliday(c carbon.Carbon) string {
            lunar := c.Lunar()
            month := lunar.Month()
            day := lunar.Day()

            for _, holiday := range chineseHolidays {
                if holiday.Month == month && holiday.Day == day {
                    return holiday.Name
                }
            }
            return ""
        }

        func main() {
            // 检查今天是否为传统节日
            today := carbon.Now()
            fmt.Println("=== 今日节日查询 ===")
            fmt.Println("公历:", today.ToDateString())
            fmt.Printf("农历: %d月%d日\n",
                today.Lunar().Month(),
                today.Lunar().Day())

            holiday := GetChineseHoliday(today)
            if holiday != "" {
                fmt.Printf("今天是: %s\n", holiday)
            } else {
                fmt.Println("今天不是传统节日")
            }

            // 列出2024年的传统节日公历日期
            fmt.Println("\n=== 2024年传统节日 ===")
            // 注意:这里简化处理,实际需要农历转公历的完整实现
            fmt.Println("春节: 2024-02-10")
            fmt.Println("元宵节: 2024-02-24")
            fmt.Println("端午节: 2024-06-10")
            fmt.Println("中秋节: 2024-09-17")

            // 实用场景:节日问候
            fmt.Println("\n=== 节日问候 ===")
            testDates := []string{
                "2024-02-10", // 春节
                "2024-06-10", // 端午
                "2024-09-17", // 中秋
            }

            for _, dateStr := range testDates {
                date := carbon.Parse(dateStr)
                holiday := GetChineseHoliday(date)
                if holiday != "" {
                    fmt.Printf("%s: 祝您%s快乐!\n",
                        date.ToDateString(),
                        holiday)
                }
            }
        }
        ---

03.农历闰月处理
    a.说明
        农历闰月是中国传统历法的重要特征。
        闰月年份会有13个月,某个月份会重复出现。
        IsLeapMonth()判断当前月是否为闰月。
        闰月计算复杂,但Carbon已经处理好底层逻辑。
        在处理农历生日等场景时需要考虑闰月情况。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 检查闰月
            fmt.Println("=== 农历闰月检查 ===")

            // 遍历一年的月份,查找闰月
            year := carbon.Parse("2024-01-01")
            fmt.Println("2024年农历闰月检查:")

            hasLeapMonth := false
            for month := 1; month <= 12; month++ {
                date := carbon.Parse(fmt.Sprintf("2024-%02d-15", month))
                lunar := date.Lunar()

                if lunar.IsLeapMonth() {
                    fmt.Printf("农历%d月是闰月\n", lunar.Month())
                    hasLeapMonth = true
                }
            }

            if !hasLeapMonth {
                fmt.Println("2024年没有闰月")
            }

            // 农历闰年示例
            fmt.Println("\n=== 农历闰年 ===")
            // 2023年农历有闰二月
            leapYearDate := carbon.Parse("2023-03-22") // 公历对应农历闰二月
            lunar := leapYearDate.Lunar()

            fmt.Println("公历:", leapYearDate.ToDateString())
            fmt.Printf("农历: %d年%d月%d日\n",
                lunar.Year(),
                lunar.Month(),
                lunar.Day())
            fmt.Println("是否闰月:", lunar.IsLeapMonth())

            // 实用场景:农历生日提醒
            fmt.Println("\n=== 农历生日提醒 ===")
            // 假设用户农历生日是三月十五
            userLunarBirthday := map[string]int{
                "month": 3,
                "day":   15,
            }

            fmt.Printf("您的农历生日: %d月%d日\n",
                userLunarBirthday["month"],
                userLunarBirthday["day"])

            // 检查今年是否有闰三月
            // 如果有闰三月,需要提醒用户选择在哪个三月过生日
            fmt.Println("提示: 如遇闰月年份,请选择在正月还是闰月庆祝生日")
        }
        ---

5.6 工作日计算

01.工作日判断
    a.说明
        IsWeekday()判断是否为工作日(周一至周五)。
        IsWeekend()判断是否为周末(周六和周日)。
        默认的工作日定义可能不适合所有国家和地区。
        可以根据实际需求自定义工作日规则。
        工作日判断在考勤、排班、项目管理等场景中非常实用。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 一周的工作日判断
            fmt.Println("=== 一周工作日判断 ===")
            weekStart := carbon.Now().StartOfWeek()

            for i := 0; i < 7; i++ {
                day := weekStart.AddDays(i)
                dayType := "工作日"
                if day.IsWeekend() {
                    dayType = "周末"
                }

                fmt.Printf("%s %s: %s\n",
                    day.ToDateString(),
                    day.ToWeekString(),
                    dayType)
            }

            // 统计本月工作日数量
            fmt.Println("\n=== 本月工作日统计 ===")
            monthStart := carbon.Now().StartOfMonth()
            daysInMonth := monthStart.DaysInMonth()

            workdays := 0
            weekends := 0

            for i := 0; i < daysInMonth; i++ {
                day := monthStart.AddDays(i)
                if day.IsWeekday() {
                    workdays++
                } else {
                    weekends++
                }
            }

            fmt.Printf("工作日: %d天\n", workdays)
            fmt.Printf("周末: %d天\n", weekends)
            fmt.Printf("总计: %d天\n", daysInMonth)

            // 查找本月所有工作日
            fmt.Println("\n=== 本月工作日列表 ===")
            for i := 0; i < daysInMonth; i++ {
                day := monthStart.AddDays(i)
                if day.IsWeekday() {
                    fmt.Printf("%s %s\n",
                        day.ToDateString(),
                        day.ToShortWeekString())
                }
            }
        }
        ---

02.工作日加减
    a.说明
        AddWorkday()和SubWorkday()方法用于工作日的加减。
        这些方法会自动跳过周末,只计算工作日。
        AddWorkdays(n)可以一次性增加n个工作日。
        在项目工期计算、交货日期估算等场景中非常实用。
        注意这些方法不考虑法定节假日,如需要需自行实现。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 工作日加减示例
            friday := carbon.Parse("2024-01-12") // 周五
            fmt.Println("=== 工作日加减 ===")
            fmt.Println("起始日期:", friday.ToDateString(), friday.ToWeekString())

            // 加1个工作日(跳过周末到周一)
            nextWorkday := friday.AddWorkday()
            fmt.Println("下1个工作日:", nextWorkday.ToDateString(), nextWorkday.ToWeekString())

            // 加5个工作日
            after5Workdays := friday.AddWorkdays(5)
            fmt.Println("5个工作日后:", after5Workdays.ToDateString(), after5Workdays.ToWeekString())

            // 减工作日
            monday := carbon.Parse("2024-01-15") // 周一
            fmt.Println("\n起始日期:", monday.ToDateString(), monday.ToWeekString())

            prevWorkday := monday.SubWorkday()
            fmt.Println("上1个工作日:", prevWorkday.ToDateString(), prevWorkday.ToWeekString())

            // 实用场景:项目工期计算
            fmt.Println("\n=== 项目工期计算 ===")
            projectStart := carbon.Parse("2024-01-15")
            workDaysNeeded := 20

            projectEnd := projectStart.AddWorkdays(workDaysNeeded)

            fmt.Println("项目开始:", projectStart.ToDateString())
            fmt.Println("需要工作日:", workDaysNeeded)
            fmt.Println("预计完成:", projectEnd.ToDateString())
            fmt.Println("实际跨度:", projectEnd.DiffInDays(projectStart), "天")

            // 计算两个日期之间的工作日数量
            fmt.Println("\n=== 工作日数量计算 ===")
            start := carbon.Parse("2024-01-01")
            end := carbon.Parse("2024-01-31")

            count := 0
            current := start
            for current.Lte(end) {
                if current.IsWeekday() {
                    count++
                }
                current = current.AddDay()
            }

            fmt.Printf("%s 至 %s\n", start.ToDateString(), end.ToDateString())
            fmt.Printf("共有 %d 个工作日\n", count)
        }
        ---

03.自定义工作日规则
    a.说明
        不同国家和地区的工作日定义可能不同。
        有些国家周五或周六是休息日而非周日。
        企业可能有特殊的工作日安排,如大小周制度。
        可以封装自定义的工作日判断和计算逻辑。
        灵活的工作日规则使Carbon适应各种业务场景。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // WorkdayRule 工作日规则接口
        type WorkdayRule interface {
            IsWorkday(c carbon.Carbon) bool
        }

        // StandardRule 标准工作日规则(周一至周五)
        type StandardRule struct{}

        func (r *StandardRule) IsWorkday(c carbon.Carbon) bool {
            return c.IsWeekday()
        }

        // MiddleEastRule 中东工作日规则(周日至周四)
        type MiddleEastRule struct{}

        func (r *MiddleEastRule) IsWorkday(c carbon.Carbon) bool {
            day := c.DayOfWeek()
            // 周日(0)到周四(4)为工作日
            return day >= 0 && day <= 4
        }

        // CustomHolidays 自定义节假日列表
        type CustomHolidays struct {
            holidays []string // YYYY-MM-DD格式
        }

        // NewCustomHolidays 创建自定义节假日
        func NewCustomHolidays(holidays []string) *CustomHolidays {
            return &CustomHolidays{holidays: holidays}
        }

        // IsHoliday 判断是否为节假日
        func (h *CustomHolidays) IsHoliday(c carbon.Carbon) bool {
            dateStr := c.ToDateString()
            for _, holiday := range h.holidays {
                if holiday == dateStr {
                    return true
                }
            }
            return false
        }

        // IsWorkday 判断是否为工作日(排除节假日)
        func (h *CustomHolidays) IsWorkday(c carbon.Carbon) bool {
            if h.IsHoliday(c) {
                return false
            }
            return c.IsWeekday()
        }

        func main() {
            date := carbon.Parse("2024-01-15")

            // 标准工作日规则
            fmt.Println("=== 标准工作日规则 ===")
            standardRule := &StandardRule{}
            fmt.Printf("%s %s: %v\n",
                date.ToDateString(),
                date.ToWeekString(),
                standardRule.IsWorkday(date))

            // 中东工作日规则
            fmt.Println("\n=== 中东工作日规则 ===")
            middleEastRule := &MiddleEastRule{}

            weekStart := date.StartOfWeek()
            for i := 0; i < 7; i++ {
                day := weekStart.AddDays(i)
                isWorkday := middleEastRule.IsWorkday(day)
                dayType := "休息日"
                if isWorkday {
                    dayType = "工作日"
                }
                fmt.Printf("%s: %s\n", day.ToWeekString(), dayType)
            }

            // 自定义节假日规则
            fmt.Println("\n=== 自定义节假日规则 ===")
            holidays := []string{
                "2024-01-01", // 元旦
                "2024-02-10", // 春节
                "2024-05-01", // 劳动节
                "2024-10-01", // 国庆节
            }

            customRule := NewCustomHolidays(holidays)

            testDates := []string{
                "2024-01-01", // 元旦(节假日)
                "2024-01-15", // 普通工作日
                "2024-02-10", // 春节(节假日)
                "2024-01-20", // 周末
            }

            for _, dateStr := range testDates {
                d := carbon.Parse(dateStr)
                isWorkday := customRule.IsWorkday(d)
                dayType := "非工作日"
                if isWorkday {
                    dayType = "工作日"
                }

                fmt.Printf("%s %s: %s\n",
                    d.ToDateString(),
                    d.ToWeekString(),
                    dayType)
            }

            // 实用场景:考虑节假日的工期计算
            fmt.Println("\n=== 考虑节假日的工期 ===")
            projectStart := carbon.Parse("2024-01-01")
            workDaysNeeded := 10

            current := projectStart
            workDaysCount := 0

            for workDaysCount < workDaysNeeded {
                if customRule.IsWorkday(current) {
                    workDaysCount++
                }
                current = current.AddDay()
            }

            fmt.Println("项目开始:", projectStart.ToDateString())
            fmt.Println("需要工作日:", workDaysNeeded)
            fmt.Println("预计完成:", current.ToDateString())
        }
        ---

6 实战应用

6.1 安装使用

01.安装Carbon库
    a.说明
        Carbon是一个纯Go语言库,使用Go Modules进行包管理。
        通过go get命令可以快速安装Carbon到项目中。
        建议使用最新稳定版本,获得最好的功能和性能。
        Carbon的v2版本是当前主流版本,API更加完善。
        安装后即可在项目中导入使用,无需额外配置。
    b.代码示例
        ---
        # 安装Carbon v2版本
        go get -u github.com/golang-module/carbon/v2

        # 安装指定版本
        go get github.com/golang-module/carbon/[email protected]

        # 查看已安装版本
        go list -m github.com/golang-module/carbon/v2
        ---

        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 验证Carbon安装
            fmt.Println("=== Carbon安装验证 ===")

            // 获取当前时间
            now := carbon.Now()
            if now.Error != nil {
                fmt.Println("Carbon未正确安装")
                return
            }

            fmt.Println("Carbon版本: v2.x")
            fmt.Println("当前时间:", now.ToDateTimeString())
            fmt.Println("时区:", now.Timezone())

            // 测试基本功能
            fmt.Println("\n=== 功能测试 ===")
            fmt.Println("格式化:", now.Format("Y-m-d H:i:s"))
            fmt.Println("明天:", now.AddDay().ToDateString())
            fmt.Println("星期:", now.ToWeekString())

            // 测试多语言
            zhCN := now.SetLocale("zh-CN")
            fmt.Println("中文星期:", zhCN.ToWeekString())

            // 测试时区转换
            utc := now.SetTimezone("UTC")
            fmt.Println("UTC时间:", utc.ToDateTimeString())

            fmt.Println("\nCarbon安装成功!")
        }
        ---

02.项目集成
    a.说明
        将Carbon集成到现有项目中需要规范化的导入和使用方式。
        建议在项目中统一时间处理逻辑,避免混用time包和Carbon。
        可以封装常用的时间操作为工具函数,提高代码复用性。
        在数据库模型中可以使用Carbon类型替代time.Time。
        合理使用Carbon可以大幅简化时间处理代码。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // TimeHelper 时间辅助工具
        type TimeHelper struct {
            DefaultTimezone string
            DefaultLocale   string
        }

        // NewTimeHelper 创建时间辅助工具
        func NewTimeHelper() *TimeHelper {
            return &TimeHelper{
                DefaultTimezone: "Asia/Shanghai",
                DefaultLocale:   "zh-CN",
            }
        }

        // Now 获取当前时间(使用默认配置)
        func (h *TimeHelper) Now() carbon.Carbon {
            return carbon.Now().
                SetTimezone(h.DefaultTimezone).
                SetLocale(h.DefaultLocale)
        }

        // Parse 解析时间字符串(使用默认配置)
        func (h *TimeHelper) Parse(value string) carbon.Carbon {
            return carbon.Parse(value).
                SetTimezone(h.DefaultTimezone).
                SetLocale(h.DefaultLocale)
        }

        // FormatDateTime 标准日期时间格式
        func (h *TimeHelper) FormatDateTime(c carbon.Carbon) string {
            return c.Format("Y-m-d H:i:s")
        }

        // FormatDate 标准日期格式
        func (h *TimeHelper) FormatDate(c carbon.Carbon) string {
            return c.ToDateString()
        }

        func main() {
            // 初始化时间辅助工具
            helper := NewTimeHelper()

            // 使用辅助工具
            fmt.Println("=== 项目集成示例 ===")

            now := helper.Now()
            fmt.Println("当前时间:", helper.FormatDateTime(now))
            fmt.Println("当前日期:", helper.FormatDate(now))

            // 解析时间
            parsed := helper.Parse("2024-01-15 10:30:00")
            fmt.Println("解析时间:", helper.FormatDateTime(parsed))

            // 时间计算
            tomorrow := now.AddDay()
            fmt.Println("明天:", helper.FormatDate(tomorrow))

            // 数据库场景示例
            fmt.Println("\n=== 数据库场景 ===")

            // 模拟数据库记录
            type User struct {
                ID        int
                Name      string
                CreatedAt carbon.Carbon
                UpdatedAt carbon.Carbon
            }

            user := User{
                ID:        1,
                Name:      "张三",
                CreatedAt: helper.Now(),
                UpdatedAt: helper.Now(),
            }

            fmt.Printf("用户ID: %d\n", user.ID)
            fmt.Printf("用户名: %s\n", user.Name)
            fmt.Printf("创建时间: %s\n", helper.FormatDateTime(user.CreatedAt))
            fmt.Printf("更新时间: %s\n", helper.FormatDateTime(user.UpdatedAt))
        }
        ---

03.最佳实践建议
    a.说明
        使用Carbon时应遵循一些最佳实践,确保代码质量和性能。
        始终检查Carbon对象的Error字段,避免使用无效对象。
        在数据库中统一使用UTC时区存储,显示时再转换为用户时区。
        避免在循环中频繁创建Carbon对象,可以考虑复用。
        使用预定义的格式化模板,提高代码可维护性。
        合理使用链式调用,但不要过度嵌套影响可读性。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // 格式化模板常量
        const (
            DateTimeFormat = "Y-m-d H:i:s"
            DateFormat     = "Y-m-d"
            TimeFormat     = "H:i:s"
        )

        // SafeParse 安全的时间解析
        func SafeParse(value string) (carbon.Carbon, error) {
            c := carbon.Parse(value)
            if c.Error != nil {
                return carbon.Carbon{}, c.Error
            }
            return c, nil
        }

        // ToUTC 转换为UTC时区(存储用)
        func ToUTC(c carbon.Carbon) carbon.Carbon {
            return c.SetTimezone("UTC")
        }

        // ToUserTimezone 转换为用户时区(显示用)
        func ToUserTimezone(c carbon.Carbon, timezone string) carbon.Carbon {
            return c.SetTimezone(timezone)
        }

        func main() {
            fmt.Println("=== 最佳实践示例 ===\n")

            // 1. 错误处理
            fmt.Println("1. 错误处理:")
            dateStr := "2024-01-15 10:30:00"
            parsed, err := SafeParse(dateStr)
            if err != nil {
                fmt.Println("解析失败:", err)
                return
            }
            fmt.Println("解析成功:", parsed.Format(DateTimeFormat))

            // 2. UTC存储
            fmt.Println("\n2. UTC存储:")
            localTime := carbon.Now()
            utcTime := ToUTC(localTime)

            fmt.Println("本地时间:", localTime.Format(DateTimeFormat))
            fmt.Println("UTC时间:", utcTime.Format(DateTimeFormat))
            fmt.Println("存储到数据库:", utcTime.ToIso8601String())

            // 3. 用户时区显示
            fmt.Println("\n3. 用户时区显示:")
            // 从数据库读取的UTC时间
            dbTime := ToUserTimezone(utcTime, "Asia/Tokyo")
            fmt.Println("东京用户看到:", dbTime.Format(DateTimeFormat))

            // 4. 对象复用
            fmt.Println("\n4. 对象复用:")
            base := carbon.Now()
            // 避免重复创建
            tomorrow := base.AddDay()
            nextWeek := base.AddWeek()
            nextMonth := base.AddMonth()

            fmt.Println("明天:", tomorrow.Format(DateFormat))
            fmt.Println("下周:", nextWeek.Format(DateFormat))
            fmt.Println("下月:", nextMonth.Format(DateFormat))

            // 5. 链式调用适度
            fmt.Println("\n5. 链式调用:")

            // 推荐:简洁的链式调用
            result1 := carbon.Now().
                AddDays(7).
                StartOfDay().
                Format(DateTimeFormat)
            fmt.Println("推荐方式:", result1)

            // 不推荐:过长的链式调用
            // 应该拆分为多个步骤
            temp := carbon.Now().AddDays(7)
            result2 := temp.StartOfDay()
            fmt.Println("拆分方式:", result2.Format(DateTimeFormat))

            // 6. 使用格式化常量
            fmt.Println("\n6. 格式化常量:")
            now := carbon.Now()
            fmt.Println("日期时间:", now.Format(DateTimeFormat))
            fmt.Println("日期:", now.Format(DateFormat))
            fmt.Println("时间:", now.Format(TimeFormat))
        }
        ---

6.2 日期范围查询

01.数据库日期查询
    a.说明
        Carbon在数据库日期范围查询中非常实用。
        可以快速构建各种时间维度的查询条件。
        使用StartOf和EndOf方法获取准确的时间边界。
        注意时区问题,确保查询条件与数据库时区一致。
        合理的日期查询是数据分析和报表生成的基础。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // QueryBuilder 查询构建器
        type QueryBuilder struct {
            table      string
            conditions []string
        }

        // NewQueryBuilder 创建查询构建器
        func NewQueryBuilder(table string) *QueryBuilder {
            return &QueryBuilder{
                table:      table,
                conditions: []string{},
            }
        }

        // WhereDate 添加日期条件
        func (qb *QueryBuilder) WhereDate(column, date string) *QueryBuilder {
            qb.conditions = append(qb.conditions,
                fmt.Sprintf("%s = '%s'", column, date))
            return qb
        }

        // WhereDateRange 添加日期范围条件
        func (qb *QueryBuilder) WhereDateRange(column string, start, end carbon.Carbon) *QueryBuilder {
            qb.conditions = append(qb.conditions,
                fmt.Sprintf("%s >= '%s' AND %s < '%s'",
                    column, start.ToDateTimeString(),
                    column, end.AddDay().ToDateTimeString()))
            return qb
        }

        // Build 构建SQL
        func (qb *QueryBuilder) Build() string {
            sql := "SELECT * FROM " + qb.table
            if len(qb.conditions) > 0 {
                sql += " WHERE "
                for i, cond := range qb.conditions {
                    if i > 0 {
                        sql += " AND "
                    }
                    sql += cond
                }
            }
            return sql + ";"
        }

        func main() {
            // 查询今天的数据
            fmt.Println("=== 查询今天的数据 ===")
            today := carbon.Now().StartOfDay()
            tomorrow := today.AddDay()

            sql1 := fmt.Sprintf(
                "SELECT * FROM orders WHERE created_at >= '%s' AND created_at < '%s';",
                today.ToDateTimeString(),
                tomorrow.ToDateTimeString(),
            )
            fmt.Println(sql1)

            // 查询本周的数据
            fmt.Println("\n=== 查询本周的数据 ===")
            weekStart := carbon.Now().StartOfWeek()
            weekEnd := carbon.Now().EndOfWeek().AddDay()

            sql2 := fmt.Sprintf(
                "SELECT * FROM orders WHERE created_at >= '%s' AND created_at < '%s';",
                weekStart.ToDateTimeString(),
                weekEnd.ToDateTimeString(),
            )
            fmt.Println(sql2)

            // 查询本月的数据
            fmt.Println("\n=== 查询本月的数据 ===")
            monthStart := carbon.Now().StartOfMonth()
            monthEnd := carbon.Now().EndOfMonth().AddDay()

            sql3 := fmt.Sprintf(
                "SELECT * FROM orders WHERE created_at >= '%s' AND created_at < '%s';",
                monthStart.ToDateTimeString(),
                monthEnd.ToDateTimeString(),
            )
            fmt.Println(sql3)

            // 使用查询构建器
            fmt.Println("\n=== 使用查询构建器 ===")

            // 查询上个月的数据
            lastMonthStart := carbon.Now().SubMonth().StartOfMonth()
            lastMonthEnd := carbon.Now().SubMonth().EndOfMonth()

            builder := NewQueryBuilder("orders")
            sql4 := builder.WhereDateRange("created_at", lastMonthStart, lastMonthEnd).Build()
            fmt.Println(sql4)

            // 查询指定日期范围
            fmt.Println("\n=== 查询指定日期范围 ===")
            start := carbon.Parse("2024-01-01")
            end := carbon.Parse("2024-01-31")

            sql5 := fmt.Sprintf(
                "SELECT * FROM sales WHERE sale_date >= '%s' AND sale_date <= '%s';",
                start.ToDateString(),
                end.ToDateString(),
            )
            fmt.Println(sql5)
        }
        ---

02.分页查询优化
    a.说明
        大数据量的日期范围查询需要考虑性能优化。
        可以使用Carbon快速计算分页所需的时间片段。
        按时间分片查询可以有效降低数据库压力。
        结合索引和合理的时间粒度能显著提升查询效率。
        在数据分析场景中,时间分片是常用的优化手段。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // TimeSlice 时间片段
        type TimeSlice struct {
            Start carbon.Carbon
            End   carbon.Carbon
        }

        // GenerateDailySlices 生成按天的时间片段
        func GenerateDailySlices(start, end carbon.Carbon) []TimeSlice {
            var slices []TimeSlice

            current := start.StartOfDay()
            endDay := end.EndOfDay()

            for current.Lte(endDay) {
                dayEnd := current.EndOfDay()
                if dayEnd.Gt(endDay) {
                    dayEnd = endDay
                }

                slices = append(slices, TimeSlice{
                    Start: current,
                    End:   dayEnd,
                })

                current = current.AddDay().StartOfDay()
            }

            return slices
        }

        // GenerateMonthlySlices 生成按月的时间片段
        func GenerateMonthlySlices(start, end carbon.Carbon) []TimeSlice {
            var slices []TimeSlice

            current := start.StartOfMonth()
            endMonth := end.EndOfMonth()

            for current.Lte(endMonth) {
                monthEnd := current.EndOfMonth()
                if monthEnd.Gt(endMonth) {
                    monthEnd = endMonth
                }

                slices = append(slices, TimeSlice{
                    Start: current,
                    End:   monthEnd,
                })

                current = current.AddMonth().StartOfMonth()
            }

            return slices
        }

        func main() {
            // 按天分片查询
            fmt.Println("=== 按天分片查询 ===")
            start := carbon.Parse("2024-01-01")
            end := carbon.Parse("2024-01-07")

            dailySlices := GenerateDailySlices(start, end)

            for i, slice := range dailySlices {
                sql := fmt.Sprintf(
                    "SELECT * FROM logs WHERE created_at >= '%s' AND created_at <= '%s';",
                    slice.Start.ToDateTimeString(),
                    slice.End.ToDateTimeString(),
                )
                fmt.Printf("片段%d: %s\n", i+1, sql)
            }

            // 按月分片查询
            fmt.Println("\n=== 按月分片查询 ===")
            yearStart := carbon.Parse("2024-01-01")
            yearEnd := carbon.Parse("2024-12-31")

            monthlySlices := GenerateMonthlySlices(yearStart, yearEnd)

            for i, slice := range monthlySlices {
                fmt.Printf("月份%d: %s ~ %s\n",
                    i+1,
                    slice.Start.ToDateString(),
                    slice.End.ToDateString())
            }

            // 实用场景:大数据量分片导出
            fmt.Println("\n=== 分片导出示例 ===")
            exportStart := carbon.Parse("2023-01-01")
            exportEnd := carbon.Parse("2023-12-31")

            slices := GenerateMonthlySlices(exportStart, exportEnd)

            for i, slice := range slices {
                fileName := fmt.Sprintf(
                    "export_%s.csv",
                    slice.Start.Format("Y-m"),
                )
                fmt.Printf("导出文件%d: %s (%s ~ %s)\n",
                    i+1,
                    fileName,
                    slice.Start.ToDateString(),
                    slice.End.ToDateString())
            }
        }
        ---

03.动态查询条件
    a.说明
        实际业务中经常需要根据用户选择动态构建查询条件。
        Carbon可以灵活处理各种时间维度的筛选需求。
        支持今天、本周、本月、自定义范围等多种查询方式。
        合理的接口设计能让时间查询更加灵活易用。
        动态查询条件在后台管理系统中非常常见。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // DateRangeType 日期范围类型
        type DateRangeType string

        const (
            Today      DateRangeType = "today"
            Yesterday  DateRangeType = "yesterday"
            ThisWeek   DateRangeType = "this_week"
            LastWeek   DateRangeType = "last_week"
            ThisMonth  DateRangeType = "this_month"
            LastMonth  DateRangeType = "last_month"
            ThisYear   DateRangeType = "this_year"
            CustomRange DateRangeType = "custom"
        )

        // DateFilter 日期筛选器
        type DateFilter struct {
            RangeType DateRangeType
            StartDate string
            EndDate   string
        }

        // GetDateRange 获取日期范围
        func (df *DateFilter) GetDateRange() (carbon.Carbon, carbon.Carbon) {
            now := carbon.Now()

            switch df.RangeType {
            case Today:
                return now.StartOfDay(), now.EndOfDay()

            case Yesterday:
                yesterday := now.SubDay()
                return yesterday.StartOfDay(), yesterday.EndOfDay()

            case ThisWeek:
                return now.StartOfWeek(), now.EndOfWeek()

            case LastWeek:
                lastWeek := now.SubWeek()
                return lastWeek.StartOfWeek(), lastWeek.EndOfWeek()

            case ThisMonth:
                return now.StartOfMonth(), now.EndOfMonth()

            case LastMonth:
                lastMonth := now.SubMonth()
                return lastMonth.StartOfMonth(), lastMonth.EndOfMonth()

            case ThisYear:
                return now.StartOfYear(), now.EndOfYear()

            case CustomRange:
                start := carbon.Parse(df.StartDate)
                end := carbon.Parse(df.EndDate)
                return start.StartOfDay(), end.EndOfDay()

            default:
                return now.StartOfDay(), now.EndOfDay()
            }
        }

        // BuildSQL 构建SQL查询
        func (df *DateFilter) BuildSQL(table, column string) string {
            start, end := df.GetDateRange()

            return fmt.Sprintf(
                "SELECT * FROM %s WHERE %s >= '%s' AND %s <= '%s';",
                table,
                column,
                start.ToDateTimeString(),
                column,
                end.ToDateTimeString(),
            )
        }

        func main() {
            // 测试各种日期范围
            fmt.Println("=== 动态日期查询 ===\n")

            filters := []DateFilter{
                {RangeType: Today},
                {RangeType: Yesterday},
                {RangeType: ThisWeek},
                {RangeType: LastWeek},
                {RangeType: ThisMonth},
                {RangeType: LastMonth},
                {RangeType: CustomRange, StartDate: "2024-01-01", EndDate: "2024-01-31"},
            }

            for _, filter := range filters {
                start, end := filter.GetDateRange()
                fmt.Printf("%s: %s ~ %s\n",
                    filter.RangeType,
                    start.ToDateString(),
                    end.ToDateString())
            }

            // 生成SQL示例
            fmt.Println("\n=== SQL查询示例 ===\n")

            filter := DateFilter{RangeType: ThisMonth}
            sql := filter.BuildSQL("orders", "created_at")
            fmt.Println(sql)

            // 自定义范围
            customFilter := DateFilter{
                RangeType: CustomRange,
                StartDate: "2024-01-01",
                EndDate:   "2024-01-31",
            }
            customSQL := customFilter.BuildSQL("sales", "sale_date")
            fmt.Println("\n", customSQL)
        }
        ---

6.3 倒计时功能

01.简单倒计时
    a.说明
        倒计时功能在活动营销、限时抢购等场景中广泛应用。
        使用Carbon可以轻松计算剩余时间。
        DiffInXxx()系列方法提供了各种时间单位的差值计算。
        可以灵活组合显示天、时、分、秒等信息。
        倒计时需要考虑时区和服务器时间同步问题。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // Countdown 倒计时结构
        type Countdown struct {
            TargetTime carbon.Carbon
        }

        // NewCountdown 创建倒计时
        func NewCountdown(target string) *Countdown {
            return &Countdown{
                TargetTime: carbon.Parse(target),
            }
        }

        // GetRemaining 获取剩余时间
        func (cd *Countdown) GetRemaining() map[string]int64 {
            now := carbon.Now()

            if now.Gte(cd.TargetTime) {
                return map[string]int64{
                    "days":    0,
                    "hours":   0,
                    "minutes": 0,
                    "seconds": 0,
                }
            }

            totalSeconds := cd.TargetTime.DiffInSeconds(now)
            days := totalSeconds / 86400
            hours := (totalSeconds % 86400) / 3600
            minutes := (totalSeconds % 3600) / 60
            seconds := totalSeconds % 60

            return map[string]int64{
                "days":    days,
                "hours":   hours,
                "minutes": minutes,
                "seconds": seconds,
            }
        }

        // Format 格式化输出
        func (cd *Countdown) Format() string {
            remaining := cd.GetRemaining()

            if remaining["days"] == 0 &&
                remaining["hours"] == 0 &&
                remaining["minutes"] == 0 &&
                remaining["seconds"] == 0 {
                return "活动已结束"
            }

            return fmt.Sprintf("%d天 %02d:%02d:%02d",
                remaining["days"],
                remaining["hours"],
                remaining["minutes"],
                remaining["seconds"])
        }

        // IsActive 是否进行中
        func (cd *Countdown) IsActive() bool {
            now := carbon.Now()
            return now.Lt(cd.TargetTime)
        }

        func main() {
            // 创建倒计时
            fmt.Println("=== 活动倒计时 ===")

            // 双十一倒计时
            doubleEleven := NewCountdown("2024-11-11 00:00:00")

            fmt.Println("目标时间:", doubleEleven.TargetTime.ToDateTimeString())
            fmt.Println("剩余时间:", doubleEleven.Format())
            fmt.Println("是否进行中:", doubleEleven.IsActive())

            // 获取详细信息
            remaining := doubleEleven.GetRemaining()
            fmt.Printf("\n详细信息:\n")
            fmt.Printf("  天数: %d\n", remaining["days"])
            fmt.Printf("  小时: %d\n", remaining["hours"])
            fmt.Printf("  分钟: %d\n", remaining["minutes"])
            fmt.Printf("  秒数: %d\n", remaining["seconds"])

            // 多个倒计时示例
            fmt.Println("\n=== 多个活动倒计时 ===")
            activities := map[string]*Countdown{
                "春节": NewCountdown("2024-02-10 00:00:00"),
                "618":  NewCountdown("2024-06-18 00:00:00"),
                "双十一": NewCountdown("2024-11-11 00:00:00"),
                "双十二": NewCountdown("2024-12-12 00:00:00"),
            }

            for name, countdown := range activities {
                fmt.Printf("%s: %s\n", name, countdown.Format())
            }

            // 近期倒计时
            fmt.Println("\n=== 近期倒计时 ===")
            soon := NewCountdown("2024-01-20 10:00:00")
            fmt.Println("倒计时:", soon.Format())
        }
        ---

02.阶段性倒计时
    a.说明
        有些活动有多个阶段,需要分阶段的倒计时提示。
        可以根据当前时间判断处于哪个阶段。
        不同阶段显示不同的倒计时信息和提示。
        阶段性倒计时常用于预热、正式、收尾等不同时期。
        合理的阶段划分能提升用户体验。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // ActivityStage 活动阶段
        type ActivityStage string

        const (
            StageNotStarted ActivityStage = "未开始"
            StagePreHeat    ActivityStage = "预热中"
            StageActive     ActivityStage = "进行中"
            StageEnding     ActivityStage = "即将结束"
            StageEnded      ActivityStage = "已结束"
        )

        // StagedActivity 阶段性活动
        type StagedActivity struct {
            Name       string
            PreHeatStart carbon.Carbon
            ActivityStart carbon.Carbon
            ActivityEnd carbon.Carbon
        }

        // GetStage 获取当前阶段
        func (sa *StagedActivity) GetStage() ActivityStage {
            now := carbon.Now()

            if now.Lt(sa.PreHeatStart) {
                return StageNotStarted
            } else if now.Between(sa.PreHeatStart, sa.ActivityStart) {
                return StagePreHeat
            } else if now.Between(sa.ActivityStart, sa.ActivityEnd.SubHours(24)) {
                return StageActive
            } else if now.Between(sa.ActivityEnd.SubHours(24), sa.ActivityEnd) {
                return StageEnding
            } else {
                return StageEnded
            }
        }

        // GetCountdown 获取倒计时信息
        func (sa *StagedActivity) GetCountdown() string {
            now := carbon.Now()
            stage := sa.GetStage()

            switch stage {
            case StageNotStarted:
                days := sa.PreHeatStart.DiffInDays(now)
                return fmt.Sprintf("距预热还有%d天", days)

            case StagePreHeat:
                hours := sa.ActivityStart.DiffInHours(now)
                return fmt.Sprintf("距开始还有%d小时", hours)

            case StageActive:
                days := sa.ActivityEnd.DiffInDays(now)
                return fmt.Sprintf("活动进行中,还有%d天", days)

            case StageEnding:
                hours := sa.ActivityEnd.DiffInHours(now)
                return fmt.Sprintf("即将结束,还有%d小时", hours)

            case StageEnded:
                return "活动已结束"

            default:
                return "未知状态"
            }
        }

        func main() {
            // 创建阶段性活动
            fmt.Println("=== 阶段性活动倒计时 ===\n")

            activity := &StagedActivity{
                Name:          "双十一大促",
                PreHeatStart:  carbon.Parse("2024-11-01 00:00:00"),
                ActivityStart: carbon.Parse("2024-11-11 00:00:00"),
                ActivityEnd:   carbon.Parse("2024-11-11 23:59:59"),
            }

            fmt.Println("活动名称:", activity.Name)
            fmt.Println("当前阶段:", activity.GetStage())
            fmt.Println("倒计时:", activity.GetCountdown())

            // 模拟不同时间点的状态
            fmt.Println("\n=== 各阶段状态模拟 ===\n")

            testTimes := []struct {
                desc string
                time string
            }{
                {"预热前", "2024-10-30 12:00:00"},
                {"预热中", "2024-11-05 12:00:00"},
                {"活动中", "2024-11-11 10:00:00"},
                {"即将结束", "2024-11-11 22:00:00"},
                {"已结束", "2024-11-12 00:00:00"},
            }

            for _, test := range testTimes {
                // 临时修改系统时间(示例)
                fmt.Printf("%s (%s):\n", test.desc, test.time)

                testTime := carbon.Parse(test.time)
                var stage ActivityStage

                if testTime.Lt(activity.PreHeatStart) {
                    stage = StageNotStarted
                    days := activity.PreHeatStart.DiffInDays(testTime)
                    fmt.Printf("  距预热还有%d天\n\n", days)
                } else if testTime.Between(activity.PreHeatStart, activity.ActivityStart) {
                    stage = StagePreHeat
                    hours := activity.ActivityStart.DiffInHours(testTime)
                    fmt.Printf("  预热中,距开始还有%d小时\n\n", hours)
                } else {
                    fmt.Println("  活动进行中或已结束\n")
                }
            }
        }
        ---

03.实时倒计时
    a.说明
        前端页面需要实时更新的倒计时效果。
        后端可以提供倒计时API,返回剩余秒数。
        前端根据秒数实时递减显示。
        需要考虑服务器时间与客户端时间的差异。
        合理的时间同步策略能提供准确的倒计时体验。
    b.代码示例
        ---
        package main

        import (
            "encoding/json"
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // CountdownResponse 倒计时API响应
        type CountdownResponse struct {
            Code       int                    `json:"code"`
            Message    string                 `json:"message"`
            Data       CountdownData          `json:"data"`
            ServerTime int64                  `json:"server_time"`
        }

        // CountdownData 倒计时数据
        type CountdownData struct {
            ActivityName string `json:"activity_name"`
            TargetTime   string `json:"target_time"`
            Remaining    int64  `json:"remaining"`      // 剩余秒数
            Days         int64  `json:"days"`
            Hours        int64  `json:"hours"`
            Minutes      int64  `json:"minutes"`
            Seconds      int64  `json:"seconds"`
            IsActive     bool   `json:"is_active"`
        }

        // GetCountdownAPI 倒计时API
        func GetCountdownAPI(targetTime string) CountdownResponse {
            target := carbon.Parse(targetTime)
            now := carbon.Now()

            remaining := int64(0)
            isActive := true

            if now.Lt(target) {
                remaining = target.DiffInSeconds(now)
            } else {
                isActive = false
            }

            days := remaining / 86400
            hours := (remaining % 86400) / 3600
            minutes := (remaining % 3600) / 60
            seconds := remaining % 60

            return CountdownResponse{
                Code:       200,
                Message:    "success",
                ServerTime: now.Timestamp(),
                Data: CountdownData{
                    ActivityName: "双十一大促",
                    TargetTime:   target.ToIso8601String(),
                    Remaining:    remaining,
                    Days:         days,
                    Hours:        hours,
                    Minutes:      minutes,
                    Seconds:      seconds,
                    IsActive:     isActive,
                },
            }
        }

        func main() {
            // 模拟API调用
            fmt.Println("=== 倒计时API响应 ===\n")

            response := GetCountdownAPI("2024-11-11 00:00:00")

            // JSON序列化
            jsonData, _ := json.MarshalIndent(response, "", "  ")
            fmt.Println(string(jsonData))

            // 前端使用示例(JavaScript伪代码)
            fmt.Println("\n=== 前端使用示例 ===\n")
            fmt.Println(`
            // 获取倒计时数据
            fetch('/api/countdown')
            .then(res => res.json())
            .then(data => {
                let remaining = data.data.remaining;
                const serverTime = data.server_time;
                const clientTime = Math.floor(Date.now() / 1000);
                const timeDiff = clientTime - serverTime;

                // 每秒更新
                setInterval(() => {
                remaining--;
                if (remaining <= 0) {
                    // 倒计时结束
                    return;
                }

                const days = Math.floor(remaining / 86400);
                const hours = Math.floor((remaining % 86400) / 3600);
                const minutes = Math.floor((remaining % 3600) / 60);
                const seconds = remaining % 60;

                // 更新显示
                document.getElementById('countdown').innerHTML =
                    days + '天 ' +
                    hours.toString().padStart(2, '0') + ':' +
                    minutes.toString().padStart(2, '0') + ':' +
                    seconds.toString().padStart(2, '0');
                }, 1000);
            });
            `)
        }
        ---

6.4 时间统计

01.访问量统计
    a.说明
        时间维度的数据统计是数据分析的基础。
        Carbon可以快速生成各种时间维度的统计报表。
        支持按小时、天、周、月、季度、年等维度聚合。
        合理的时间分组能直观展示数据趋势。
        统计功能在后台管理系统中应用广泛。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // VisitRecord 访问记录
        type VisitRecord struct {
            ID        int
            URL       string
            CreatedAt carbon.Carbon
        }

        // HourlyStats 按小时统计
        func HourlyStats(records []VisitRecord, date carbon.Carbon) map[int]int {
            stats := make(map[int]int)

            dayStart := date.StartOfDay()
            dayEnd := date.EndOfDay()

            for _, record := range records {
                if record.CreatedAt.Between(dayStart, dayEnd) {
                    hour := record.CreatedAt.Hour()
                    stats[hour]++
                }
            }

            return stats
        }

        // DailyStats 按天统计
        func DailyStats(records []VisitRecord, start, end carbon.Carbon) map[string]int {
            stats := make(map[string]int)

            for _, record := range records {
                if record.CreatedAt.Between(start, end) {
                    date := record.CreatedAt.ToDateString()
                    stats[date]++
                }
            }

            return stats
        }

        // MonthlyStats 按月统计
        func MonthlyStats(records []VisitRecord, year int) map[string]int {
            stats := make(map[string]int)

            for _, record := range records {
                if record.CreatedAt.Year() == year {
                    month := record.CreatedAt.Format("Y-m")
                    stats[month]++
                }
            }

            return stats
        }

        func main() {
            // 模拟访问记录
            records := []VisitRecord{
                {1, "/home", carbon.Parse("2024-01-15 08:30:00")},
                {2, "/about", carbon.Parse("2024-01-15 09:15:00")},
                {3, "/product", carbon.Parse("2024-01-15 10:20:00")},
                {4, "/home", carbon.Parse("2024-01-15 14:45:00")},
                {5, "/contact", carbon.Parse("2024-01-16 09:30:00")},
                {6, "/home", carbon.Parse("2024-01-16 11:00:00")},
            }

            // 按小时统计
            fmt.Println("=== 今日访问量(按小时) ===")
            today := carbon.Parse("2024-01-15")
            hourlyStats := HourlyStats(records, today)

            for hour := 0; hour < 24; hour++ {
                count := hourlyStats[hour]
                if count > 0 {
                    fmt.Printf("%02d:00 - %d次\n", hour, count)
                }
            }

            // 按天统计
            fmt.Println("\n=== 本周访问量(按天) ===")
            weekStart := carbon.Parse("2024-01-15").StartOfWeek()
            weekEnd := carbon.Parse("2024-01-15").EndOfWeek()
            dailyStats := DailyStats(records, weekStart, weekEnd)

            current := weekStart
            for current.Lte(weekEnd) {
                date := current.ToDateString()
                count := dailyStats[date]
                fmt.Printf("%s %s: %d次\n",
                    date,
                    current.ToWeekString(),
                    count)
                current = current.AddDay()
            }

            // 按月统计
            fmt.Println("\n=== 2024年访问量(按月) ===")
            monthlyStats := MonthlyStats(records, 2024)

            for month := 1; month <= 12; month++ {
                monthKey := fmt.Sprintf("2024-%02d", month)
                count := monthlyStats[monthKey]
                if count > 0 {
                    fmt.Printf("%s: %d次\n", monthKey, count)
                }
            }
        }
        ---

02.业绩统计报表
    a.说明
        业绩统计需要按时间维度聚合销售数据。
        Carbon可以快速生成各种周期的业绩报表。
        支持环比、同比等多维度对比分析。
        合理的统计粒度有助于发现业务趋势。
        报表功能是商业智能系统的核心。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // SalesRecord 销售记录
        type SalesRecord struct {
            ID        int
            Amount    float64
            CreatedAt carbon.Carbon
        }

        // PeriodStats 周期统计
        type PeriodStats struct {
            Period string
            Count  int
            Amount float64
        }

        // DailySalesStats 每日销售统计
        func DailySalesStats(records []SalesRecord, start, end carbon.Carbon) []PeriodStats {
            statsMap := make(map[string]*PeriodStats)

            current := start.StartOfDay()
            for current.Lte(end) {
                date := current.ToDateString()
                statsMap[date] = &PeriodStats{
                    Period: date,
                    Count:  0,
                    Amount: 0,
                }
                current = current.AddDay()
            }

            for _, record := range records {
                if record.CreatedAt.Between(start, end) {
                    date := record.CreatedAt.ToDateString()
                    if stats, ok := statsMap[date]; ok {
                        stats.Count++
                        stats.Amount += record.Amount
                    }
                }
            }

            var result []PeriodStats
            current = start.StartOfDay()
            for current.Lte(end) {
                date := current.ToDateString()
                result = append(result, *statsMap[date])
                current = current.AddDay()
            }

            return result
        }

        // MonthlySalesStats 每月销售统计
        func MonthlySalesStats(records []SalesRecord, year int) []PeriodStats {
            statsMap := make(map[string]*PeriodStats)

            for month := 1; month <= 12; month++ {
                period := fmt.Sprintf("%d-%02d", year, month)
                statsMap[period] = &PeriodStats{
                    Period: period,
                    Count:  0,
                    Amount: 0,
                }
            }

            for _, record := range records {
                if record.CreatedAt.Year() == year {
                    period := record.CreatedAt.Format("Y-m")
                    if stats, ok := statsMap[period]; ok {
                        stats.Count++
                        stats.Amount += record.Amount
                    }
                }
            }

            var result []PeriodStats
            for month := 1; month <= 12; month++ {
                period := fmt.Sprintf("%d-%02d", year, month)
                result = append(result, *statsMap[period])
            }

            return result
        }

        func main() {
            // 模拟销售数据
            records := []SalesRecord{
                {1, 100.50, carbon.Parse("2024-01-01 10:00:00")},
                {2, 200.00, carbon.Parse("2024-01-01 14:00:00")},
                {3, 150.75, carbon.Parse("2024-01-02 09:00:00")},
                {4, 300.00, carbon.Parse("2024-01-02 15:00:00")},
                {5, 250.50, carbon.Parse("2024-01-03 11:00:00")},
            }

            // 每日销售统计
            fmt.Println("=== 本周销售统计 ===")
            weekStart := carbon.Parse("2024-01-01")
            weekEnd := carbon.Parse("2024-01-07")

            dailyStats := DailySalesStats(records, weekStart, weekEnd)

            totalAmount := 0.0
            totalCount := 0

            for _, stats := range dailyStats {
                fmt.Printf("%s: %d笔订单, ¥%.2f\n",
                    stats.Period,
                    stats.Count,
                    stats.Amount)
                totalAmount += stats.Amount
                totalCount += stats.Count
            }

            fmt.Printf("\n合计: %d笔订单, ¥%.2f\n", totalCount, totalAmount)
            if totalCount > 0 {
                fmt.Printf("平均: ¥%.2f/笔\n", totalAmount/float64(totalCount))
            }

            // 每月销售统计
            fmt.Println("\n=== 2024年月度销售 ===")
            monthlyStats := MonthlySalesStats(records, 2024)

            yearTotal := 0.0
            yearCount := 0

            for _, stats := range monthlyStats {
                if stats.Count > 0 {
                    fmt.Printf("%s: %d笔订单, ¥%.2f\n",
                        stats.Period,
                        stats.Count,
                        stats.Amount)
                    yearTotal += stats.Amount
                    yearCount += stats.Count
                }
            }

            fmt.Printf("\n年度合计: %d笔订单, ¥%.2f\n", yearCount, yearTotal)
        }
        ---

03.用户行为分析
    a.说明
        用户行为分析需要按时间维度统计用户活跃度。
        可以分析用户的登录时间、活跃时段等特征。
        时间分布图能直观展示用户行为规律。
        合理的时间粒度选择影响分析效果。
        用户行为分析是产品优化的重要依据。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // UserActivity 用户活动记录
        type UserActivity struct {
            UserID    int
            Action    string
            CreatedAt carbon.Carbon
        }

        // ActiveHours 活跃时段分析
        func ActiveHours(activities []UserActivity) map[int]int {
            hourStats := make(map[int]int)

            for _, activity := range activities {
                hour := activity.CreatedAt.Hour()
                hourStats[hour]++
            }

            return hourStats
        }

        // ActiveDays 活跃日期分析
        func ActiveDays(activities []UserActivity, userID int) []string {
            dateSet := make(map[string]bool)

            for _, activity := range activities {
                if activity.UserID == userID {
                    date := activity.CreatedAt.ToDateString()
                    dateSet[date] = true
                }
            }

            var dates []string
            for date := range dateSet {
                dates = append(dates, date)
            }

            return dates
        }

        // WeekdayDistribution 工作日分布
        func WeekdayDistribution(activities []UserActivity) map[string]int {
            weekdayStats := make(map[string]int)

            for _, activity := range activities {
                weekday := activity.CreatedAt.ToWeekString()
                weekdayStats[weekday]++
            }

            return weekdayStats
        }

        func main() {
            // 模拟用户活动数据
            activities := []UserActivity{
                {1, "login", carbon.Parse("2024-01-15 08:30:00")},
                {1, "view", carbon.Parse("2024-01-15 09:00:00")},
                {2, "login", carbon.Parse("2024-01-15 10:00:00")},
                {1, "click", carbon.Parse("2024-01-15 14:00:00")},
                {2, "view", carbon.Parse("2024-01-15 15:00:00")},
                {1, "login", carbon.Parse("2024-01-16 09:00:00")},
            }

            // 活跃时段分析
            fmt.Println("=== 用户活跃时段分析 ===")
            hourStats := ActiveHours(activities)

            for hour := 0; hour < 24; hour++ {
                count := hourStats[hour]
                if count > 0 {
                    bar := ""
                    for i := 0; i < count; i++ {
                        bar += "█"
                    }
                    fmt.Printf("%02d:00 %s %d\n", hour, bar, count)
                }
            }

            // 用户活跃天数
            fmt.Println("\n=== 用户活跃天数 ===")
            activeDays := ActiveDays(activities, 1)
            fmt.Printf("用户1活跃天数: %d天\n", len(activeDays))
            for _, date := range activeDays {
                fmt.Printf("  - %s\n", date)
            }

            // 星期分布
            fmt.Println("\n=== 星期活跃分布 ===")
            weekdayStats := WeekdayDistribution(activities)

            weekdays := []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
            for _, weekday := range weekdays {
                count := weekdayStats[weekday]
                fmt.Printf("%s: %d次\n", weekday, count)
            }
        }
        ---

6.5 定时任务

01.定时任务调度
    a.说明
        Carbon可以帮助计算和判断定时任务的执行时间。
        配合cron表达式可以实现灵活的任务调度。
        可以判断任务是否应该在当前时间执行。
        支持各种周期性任务的时间计算。
        合理的任务调度能提高系统效率。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // Task 定时任务
        type Task struct {
            Name      string
            Schedule  string // 简化的调度规则
            LastRun   carbon.Carbon
            NextRun   carbon.Carbon
        }

        // ShouldRun 判断是否应该执行
        func (t *Task) ShouldRun() bool {
            now := carbon.Now()
            return now.Gte(t.NextRun)
        }

        // CalculateNextRun 计算下次执行时间
        func (t *Task) CalculateNextRun() {
            now := carbon.Now()

            switch t.Schedule {
            case "daily":
                // 每天执行
                t.NextRun = now.AddDay().StartOfDay()

            case "hourly":
                // 每小时执行
                t.NextRun = now.AddHour().StartOfHour()

            case "weekly":
                // 每周执行
                t.NextRun = now.AddWeek().StartOfWeek()

            case "monthly":
                // 每月执行
                t.NextRun = now.AddMonth().StartOfMonth()

            default:
                t.NextRun = now.AddDay()
            }
        }

        // Run 执行任务
        func (t *Task) Run() {
            fmt.Printf("[%s] 执行任务: %s\n",
                carbon.Now().ToDateTimeString(),
                t.Name)

            t.LastRun = carbon.Now()
            t.CalculateNextRun()
        }

        func main() {
            // 创建定时任务
            fmt.Println("=== 定时任务调度 ===\n")

            tasks := []*Task{
                {
                    Name:     "每日数据备份",
                    Schedule: "daily",
                    LastRun:  carbon.Yesterday(),
                },
                {
                    Name:     "每小时日志清理",
                    Schedule: "hourly",
                    LastRun:  carbon.Now().SubHour(),
                },
                {
                    Name:     "每周报表生成",
                    Schedule: "weekly",
                    LastRun:  carbon.Now().SubWeek(),
                },
            }

            // 初始化下次执行时间
            for _, task := range tasks {
                task.CalculateNextRun()
            }

            // 显示任务列表
            fmt.Println("任务列表:")
            for i, task := range tasks {
                fmt.Printf("%d. %s\n", i+1, task.Name)
                fmt.Printf("   调度: %s\n", task.Schedule)
                fmt.Printf("   上次执行: %s\n", task.LastRun.ToDateTimeString())
                fmt.Printf("   下次执行: %s\n\n", task.NextRun.ToDateTimeString())
            }

            // 检查应该执行的任务
            fmt.Println("=== 检查待执行任务 ===")
            for _, task := range tasks {
                if task.ShouldRun() {
                    task.Run()
                } else {
                    remaining := task.NextRun.DiffInSeconds(carbon.Now())
                    fmt.Printf("[%s] %s 还需等待 %d秒\n",
                        carbon.Now().ToDateTimeString(),
                        task.Name,
                        remaining)
                }
            }
        }
        ---

02.特定时间执行
    a.说明
        有些任务需要在特定的时间点执行。
        可以使用Carbon判断是否到达指定时间。
        支持每天特定时刻、每周特定日期等场景。
        精确的时间判断确保任务按时执行。
        这类任务在报表生成、数据同步等场景中常见。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        // ScheduledTask 预定任务
        type ScheduledTask struct {
            Name        string
            ExecuteTime string // HH:MM格式
            Weekday     int    // 0=周日, 1=周一, ..., 6=周六, -1=每天
        }

        // ShouldExecute 判断是否应该执行
        func (st *ScheduledTask) ShouldExecute() bool {
            now := carbon.Now()

            // 检查星期
            if st.Weekday != -1 && now.DayOfWeek() != st.Weekday {
                return false
            }

            // 检查时间
            currentTime := now.Format("H:i")
            return currentTime == st.ExecuteTime
        }

        // GetNextExecutionTime 获取下次执行时间
        func (st *ScheduledTask) GetNextExecutionTime() carbon.Carbon {
            now := carbon.Now()
            targetTime := carbon.Parse(now.ToDateString() + " " + st.ExecuteTime + ":00")

            // 如果今天的时间已过,找下一个执行日
            if now.Gte(targetTime) {
                targetTime = targetTime.AddDay()
            }

            // 如果指定了星期几
            if st.Weekday != -1 {
                for targetTime.DayOfWeek() != st.Weekday {
                    targetTime = targetTime.AddDay()
                }
            }

            return targetTime
        }

        func main() {
            // 创建预定任务
            fmt.Println("=== 预定任务列表 ===\n")

            tasks := []*ScheduledTask{
                {
                    Name:        "每日早报",
                    ExecuteTime: "09:00",
                    Weekday:     -1, // 每天
                },
                {
                    Name:        "周一晨会",
                    ExecuteTime: "10:00",
                    Weekday:     1, // 周一
                },
                {
                    Name:        "周五总结",
                    ExecuteTime: "17:00",
                    Weekday:     5, // 周五
                },
                {
                    Name:        "午间提醒",
                    ExecuteTime: "12:00",
                    Weekday:     -1, // 每天
                },
            }

            // 显示任务信息
            for i, task := range tasks {
                weekdayStr := "每天"
                if task.Weekday != -1 {
                    weekdays := []string{"周日", "周一", "周二", "周三", "周四", "周五", "周六"}
                    weekdayStr = weekdays[task.Weekday]
                }

                nextRun := task.GetNextExecutionTime()

                fmt.Printf("%d. %s\n", i+1, task.Name)
                fmt.Printf("   时间: %s %s\n", weekdayStr, task.ExecuteTime)
                fmt.Printf("   下次执行: %s\n\n", nextRun.ToDateTimeString())
            }

            // 检查当前应执行的任务
            fmt.Println("=== 当前应执行的任务 ===")
            now := carbon.Now()
            fmt.Printf("当前时间: %s %s %s\n\n",
                now.ToDateString(),
                now.ToWeekString(),
                now.Format("H:i"))

            hasTask := false
            for _, task := range tasks {
                if task.ShouldExecute() {
                    fmt.Printf("✓ %s 应该执行\n", task.Name)
                    hasTask = true
                }
            }

            if !hasTask {
                fmt.Println("当前没有需要执行的任务")
            }
        }
        ---

03.延迟任务处理
    a.说明
        延迟任务需要在指定时间后执行。
        Carbon可以计算任务的到期时间。
        支持基于时间戳或相对时间的延迟。
        延迟任务常用于消息推送、订单超时等场景。
        准确的延迟计算确保任务按时处理。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "time"
            "github.com/golang-module/carbon/v2"
        )

        // DelayedTask 延迟任务
        type DelayedTask struct {
            ID          int
            Name        string
            CreatedAt   carbon.Carbon
            DelayDuration time.Duration
            ExecuteAt   carbon.Carbon
            Status      string
        }

        // NewDelayedTask 创建延迟任务
        func NewDelayedTask(id int, name string, delay time.Duration) *DelayedTask {
            now := carbon.Now()
            return &DelayedTask{
                ID:            id,
                Name:          name,
                CreatedAt:     now,
                DelayDuration: delay,
                ExecuteAt:     now.AddDuration(delay),
                Status:        "pending",
            }
        }

        // ShouldExecute 判断是否到期
        func (dt *DelayedTask) ShouldExecute() bool {
            return carbon.Now().Gte(dt.ExecuteAt)
        }

        // Execute 执行任务
        func (dt *DelayedTask) Execute() {
            if dt.ShouldExecute() {
                fmt.Printf("[%s] 执行延迟任务: %s\n",
                    carbon.Now().ToDateTimeString(),
                    dt.Name)
                dt.Status = "completed"
            } else {
                fmt.Printf("[%s] 任务 %s 未到执行时间\n",
                    carbon.Now().ToDateTimeString(),
                    dt.Name)
            }
        }

        // GetRemainingTime 获取剩余时间
        func (dt *DelayedTask) GetRemainingTime() string {
            now := carbon.Now()
            if now.Gte(dt.ExecuteAt) {
                return "已到期"
            }

            remaining := dt.ExecuteAt.DiffInSeconds(now)
            hours := remaining / 3600
            minutes := (remaining % 3600) / 60
            seconds := remaining % 60

            return fmt.Sprintf("%d小时%d分%d秒", hours, minutes, seconds)
        }

        func main() {
            // 创建延迟任务
            fmt.Println("=== 延迟任务队列 ===\n")

            tasks := []*DelayedTask{
                NewDelayedTask(1, "发送欢迎邮件", 5*time.Minute),
                NewDelayedTask(2, "订单超时取消", 30*time.Minute),
                NewDelayedTask(3, "优惠券过期提醒", 2*time.Hour),
                NewDelayedTask(4, "会员到期通知", 24*time.Hour),
            }

            // 显示任务列表
            fmt.Println("任务列表:")
            for _, task := range tasks {
                fmt.Printf("任务%d: %s\n", task.ID, task.Name)
                fmt.Printf("  创建时间: %s\n", task.CreatedAt.ToDateTimeString())
                fmt.Printf("  执行时间: %s\n", task.ExecuteAt.ToDateTimeString())
                fmt.Printf("  剩余时间: %s\n", task.GetRemainingTime())
                fmt.Printf("  状态: %s\n\n", task.Status)
            }

            // 检查到期任务
            fmt.Println("=== 检查到期任务 ===")
            for _, task := range tasks {
                if task.ShouldExecute() {
                    task.Execute()
                }
            }

            // 实用场景:订单超时处理
            fmt.Println("\n=== 订单超时处理示例 ===")

            type Order struct {
                ID        int
                CreatedAt carbon.Carbon
                Timeout   time.Duration
            }

            order := Order{
                ID:        12345,
                CreatedAt: carbon.Now().SubMinutes(35),
                Timeout:   30 * time.Minute,
            }

            expireTime := order.CreatedAt.AddDuration(order.Timeout)
            now := carbon.Now()

            fmt.Printf("订单ID: %d\n", order.ID)
            fmt.Printf("创建时间: %s\n", order.CreatedAt.ToDateTimeString())
            fmt.Printf("超时时间: %s\n", expireTime.ToDateTimeString())
            fmt.Printf("当前时间: %s\n", now.ToDateTimeString())

            if now.Gt(expireTime) {
                fmt.Println("状态: 订单已超时,自动取消")
            } else {
                remaining := expireTime.DiffInMinutes(now)
                fmt.Printf("状态: 订单进行中,还有 %d 分钟超时\n", remaining)
            }
        }
        ---

6.6 常见问题

01.时区问题处理
    a.说明
        时区是Carbon使用中最常见的问题之一。
        数据库存储UTC时间,显示时转换为用户时区是最佳实践。
        跨时区业务需要特别注意时间的存储和展示。
        Carbon自动处理夏令时等复杂时区规则。
        正确处理时区能避免大量的时间错误。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 问题1: 数据库时间与显示时间不一致
            fmt.Println("=== 问题1: 时区不一致 ===\n")

            // 错误做法:直接存储本地时间
            localTime := carbon.Now()
            fmt.Println("错误:存储本地时间:", localTime.ToDateTimeString())

            // 正确做法:存储UTC时间
            utcTime := carbon.Now().SetTimezone("UTC")
            fmt.Println("正确:存储UTC时间:", utcTime.ToDateTimeString())

            // 显示时转换为用户时区
            userTimezone := "Asia/Tokyo"
            displayTime := utcTime.SetTimezone(userTimezone)
            fmt.Println("用户看到:", displayTime.ToDateTimeString())

            // 问题2: 解析字符串时的时区
            fmt.Println("\n=== 问题2: 解析时区 ===\n")

            // 未指定时区,使用系统默认
            parsed1 := carbon.Parse("2024-01-15 10:00:00")
            fmt.Println("默认时区:", parsed1.Timezone())

            // 指定时区解析
            parsed2 := carbon.ParseByFormat(
                "2024-01-15 10:00:00",
                "Y-m-d H:i:s",
                "America/New_York",
            )
            fmt.Println("纽约时区:", parsed2.Timezone())

            // 问题3: 时区转换保持时刻
            fmt.Println("\n=== 问题3: 时区转换 ===\n")

            beijing := carbon.Parse("2024-01-15 10:00:00").
                SetTimezone("Asia/Shanghai")
            fmt.Println("北京时间:", beijing.ToDateTimeString())

            // 转换到纽约时区(时刻不变)
            newYork := beijing.SetTimezone("America/New_York")
            fmt.Println("纽约时间:", newYork.ToDateTimeString())

            // 验证时间戳相同
            fmt.Printf("时间戳相同: %v\n",
                beijing.Timestamp() == newYork.Timestamp())
        }
        ---

02.格式化问题
    a.说明
        格式化是另一个常见问题点。
        Carbon支持PHP风格格式符,与Go标准库不同。
        需要注意格式符的大小写,Y和y代表不同含义。
        日期格式要根据目标系统的要求选择。
        掌握常用格式符能解决大部分格式化需求。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            now := carbon.Now()

            // 问题1: 格式符大小写
            fmt.Println("=== 问题1: 格式符大小写 ===\n")
            fmt.Println("Y(4位年):", now.Format("Y"))     // 2024
            fmt.Println("y(2位年):", now.Format("y"))     // 24
            fmt.Println("m(2位月):", now.Format("m"))     // 01
            fmt.Println("n(1位月):", now.Format("n"))     // 1
            fmt.Println("d(2位日):", now.Format("d"))     // 15
            fmt.Println("j(1位日):", now.Format("j"))     // 15

            // 问题2: 12/24小时制混淆
            fmt.Println("\n=== 问题2: 12/24小时制 ===\n")
            fmt.Println("H(24小时):", now.Format("H:i"))  // 14:30
            fmt.Println("h(12小时):", now.Format("h:i A")) // 02:30 PM

            // 问题3: 标准格式输出
            fmt.Println("\n=== 问题3: 标准格式 ===\n")

            // ISO8601格式
            fmt.Println("ISO8601:", now.ToIso8601String())

            // 数据库格式
            fmt.Println("MySQL:", now.ToDateTimeString())

            // 自定义格式
            fmt.Println("自定义:", now.Format("Y-m-d H:i:s"))

            // 问题4: 多语言格式
            fmt.Println("\n=== 问题4: 多语言 ===\n")

            zhCN := now.SetLocale("zh-CN")
            fmt.Println("中文:", zhCN.Format("Y年m月d日 l"))

            en := now.SetLocale("en")
            fmt.Println("英文:", en.Format("l, F d, Y"))

            // 问题5: 常见错误
            fmt.Println("\n=== 问题5: 常见错误 ===\n")

            // 错误:使用Go标准库格式
            // fmt.Println(now.Format("2006-01-02")) // 错误!

            // 正确:使用Carbon格式符
            fmt.Println("正确:", now.Format("Y-m-d"))

            // 或使用预定义方法
            fmt.Println("推荐:", now.ToDateString())
        }
        ---

03.性能优化建议
    a.说明
        合理使用Carbon可以避免性能问题。
        避免在循环中频繁创建Carbon对象。
        使用预定义格式方法比自定义格式更快。
        批量操作时考虑复用Carbon实例。
        理解Carbon的不可变特性有助于优化代码。
    b.代码示例
        ---
        package main

        import (
            "fmt"
            "time"
            "github.com/golang-module/carbon/v2"
        )

        func main() {
            // 性能建议1: 避免重复创建
            fmt.Println("=== 建议1: 对象复用 ===\n")

            // 不推荐:循环中重复创建
            start := time.Now()
            for i := 0; i < 1000; i++ {
                _ = carbon.Now().ToDateString()
            }
            elapsed1 := time.Since(start)
            fmt.Printf("重复创建: %v\n", elapsed1)

            // 推荐:复用对象
            start = time.Now()
            now := carbon.Now()
            for i := 0; i < 1000; i++ {
                _ = now.ToDateString()
            }
            elapsed2 := time.Since(start)
            fmt.Printf("对象复用: %v\n", elapsed2)

            // 性能建议2: 使用预定义方法
            fmt.Println("\n=== 建议2: 预定义方法 ===\n")

            now = carbon.Now()

            // 较慢:自定义格式
            start = time.Now()
            for i := 0; i < 1000; i++ {
                _ = now.Format("Y-m-d H:i:s")
            }
            elapsed1 = time.Since(start)
            fmt.Printf("自定义格式: %v\n", elapsed1)

            // 较快:预定义方法
            start = time.Now()
            for i := 0; i < 1000; i++ {
                _ = now.ToDateTimeString()
            }
            elapsed2 = time.Since(start)
            fmt.Printf("预定义方法: %v\n", elapsed2)

            // 性能建议3: 批量操作优化
            fmt.Println("\n=== 建议3: 批量操作 ===\n")

            // 不推荐:逐个处理
            dates := make([]string, 100)
            start = time.Now()
            for i := 0; i < len(dates); i++ {
                dates[i] = carbon.Now().AddDays(i).ToDateString()
            }
            elapsed1 = time.Since(start)
            fmt.Printf("逐个处理: %v\n", elapsed1)

            // 推荐:基准复用
            dates = make([]string, 100)
            start = time.Now()
            base := carbon.Now()
            for i := 0; i < len(dates); i++ {
                dates[i] = base.AddDays(i).ToDateString()
            }
            elapsed2 = time.Since(start)
            fmt.Printf("基准复用: %v\n", elapsed2)

            // 性能建议4: 错误检查
            fmt.Println("\n=== 建议4: 错误处理 ===\n")

            // 推荐:使用Error字段
            parsed := carbon.Parse("invalid-date")
            if parsed.Error != nil {
                fmt.Println("解析失败:", parsed.Error)
            }

            // 推荐:先验证再使用
            if parsed.IsZero() {
                fmt.Println("时间对象无效")
            }

            // 建议5: 合理的缓存策略
            fmt.Println("\n=== 建议5: 缓存策略 ===\n")

            // 对于不变的时间点,可以缓存
            type Cache struct {
                todayStart carbon.Carbon
                todayEnd   carbon.Carbon
            }

            cache := &Cache{
                todayStart: carbon.Now().StartOfDay(),
                todayEnd:   carbon.Now().EndOfDay(),
            }

            fmt.Println("缓存的今日范围:")
            fmt.Println("开始:", cache.todayStart.ToDateTimeString())
            fmt.Println("结束:", cache.todayEnd.ToDateTimeString())

            // 注意:跨天时需要更新缓存
            fmt.Println("\n提示:定时更新缓存以保持准确性")
        }
        ---