Menu
CoddyTech

时间运算

本课属于 Coddy GO 学习旅程的“逻辑与流程”单元。第 63 课,共 68 课。

现在你已经了解了 time.Time 对象和 time.Duration 值,可以执行算术运算来计算过去或未来的时间。Go 提供了两个用于时间运算的重要方法:Add 和 Sub。

Add 方法接收一个 time.Duration,并返回一个新的 time.Time,表示原来的时间加上这段时长:

now := time.Now()
tomorrow := now.Add(24 * time.Hour)
fmt.Println(tomorrow)

Sub 方法有两种用法。从一个 time.Time 中减去另一个 time.Time 时,它会返回一个 time.Duration,表示两者之间的差值:

start := time.Now()
end := start.Add(2 * time.Hour)
difference := end.Sub(start) // 返回 2h0m0s

这些方法可以轻松计算截止时间、测量经过的时间或安排未来的事件。原始的 time.Time 对象保持不变,这两个方法都会返回新值,这符合 Go 倾向于使用不可变操作的做法。

challenge icon

挑战

简单

创建一个项目截止日期计算器,使用时间运算来确定项目里程碑和截止日期。本次挑战将测试你使用 Add 和 Sub 方法处理 time.Time 对象的能力,以计算未来日期和事件之间的时间差。

你将收到两个输入:

  • 一个字符串,包含项目开始信息,格式为 "year:month:day:hour:minute"(例如:"2024:1:15:9:0")
  • 一个字符串,包含任务时长,格式为 "task1:duration_value:duration_unit,task2:duration_value:duration_unit"(例如:"Planning:5:Day,Development:3:Week,Testing:10:Day")

你的任务是:

  1. 通过按冒号拆分第一个输入,提取年、月、日、小时和分钟的值
  2. 将这些字符串值转换为整数,并使用 time.Date 创建项目开始时间(位置使用 time.UTC,秒和纳秒设为 0)
  3. 通过按逗号拆分第二个输入,获取各个任务条目
  4. 对于每个任务条目,按冒号拆分以提取任务名称、时长值和时长单位
  5. 将时长值转换为整数,并使用相应的常量创建 time.Duration 对象:
    • 对于 "Day":乘以 24 * time.Hour
    • 对于 "Week":乘以 7 * 24 * time.Hour
    • 对于 "Hour":乘以 time.Hour
  6. 显示应用程序标题:"=== PROJECT DEADLINE CALCULATOR ==="
  7. 显示项目开始时间:"Project start time: [start_time_object]"
  8. 通过将每个任务的时长加到前一个任务的结束时间上来计算任务截止时间(第一个任务从项目开始时间开始):
  9. 对于每个任务,显示:
    • "Task: [task_name]"
    • " Duration: [duration_object]"
    • " Start: [task_start_time]"
    • " End: [task_end_time]"(使用 Add 方法计算)
  10. 计算并显示项目时间线:
    • "=== PROJECT TIMELINE ==="
    • "Project start: [start_time_object]"
    • "Project end: [final_task_end_time]"
    • "Total project duration: [total_duration_object]"(使用 Sub 方法计算项目结束时间与开始时间之间的差值)
  11. 显示任务分析结果:
    • "=== TASK ANALYSIS ==="
    • "Number of tasks: [number_of_tasks]"
    • "Longest task: [longest_task_name] ([longest_duration_object])"
    • "Shortest task: [shortest_task_name] ([shortest_duration_object])"
  12. 计算连续任务之间的时间,并显示间隔:
    • "=== TASK TRANSITIONS ==="
    • 对于每对连续任务:"[first_task_name] to [second_task_name]: [time_difference_object]"(由于任务连续进行,结果应为 0)
  13. 显示项目统计信息:
    • "=== PROJECT STATISTICS ==="
    • "Total working days: [total_duration_in_hours_divided_by_24]"
    • "Total working hours: [total_duration_in_hours]"
    • "Project spans [number_of_calendar_days] calendar days"
  14. 显示完成消息:"Project timeline calculation completed successfully"

使用 time 包执行时间操作,使用 strings 包拆分输入字符串,使用 strconv 包将字符串转换为整数,并使用 fmt 包格式化输出。请记住,Add 方法会返回一个新的 time.Time 对象,表示原始时间加上时长后的时间;Sub 方法会返回一个 time.Duration,表示两个时间之间的差值。本次挑战将演示如何使用时间运算构建完整的项目时间线。

亲手试试

package main

import (
	"fmt"
	"strconv"
	"strings"
	"time"
)

func main() {
	// 读取输入
	var startInfo string
	var taskInfo string
	fmt.Scanln(&startInfo)
	fmt.Scanln(&taskInfo)
	
	// 解析开始时间信息
	startParts := strings.Split(startInfo, ":")
	year, _ := strconv.Atoi(startParts[0])
	month, _ := strconv.Atoi(startParts[1])
	day, _ := strconv.Atoi(startParts[2])
	hour, _ := strconv.Atoi(startParts[3])
	minute, _ := strconv.Atoi(startParts[4])
	
	// 创建项目开始时间
	startTime := time.Date(year, time.Month(month), day, hour, minute, 0, 0, time.UTC)
	
	// 解析任务信息
	taskEntries := strings.Split(taskInfo, ",")
	
	// TODO:在下方编写你的代码
	// 处理每条任务记录,提取名称、时长值和单位
	// 为每个任务创建时长对象
	// 计算任务的开始和结束时间
	// 找出耗时最长和最短的任务
	// 计算项目统计数据
	// 显示所有要求的输出部分
	
	// 输出将由你在上方编写的代码生成
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

逻辑与流程中的所有课

自己练习: Go 在线编译器