Phép tính thời gian
Thuộc phần Logic và luồng điều khiển trong hành trình GO của Coddy. Bài học 63 trên 68.
Giờ đây, khi đã hiểu các đối tượng time.Time và giá trị time.Duration, bạn có thể thực hiện các phép tính số học để tính thời điểm trong quá khứ hoặc tương lai. Go cung cấp hai phương thức thiết yếu để tính toán thời gian: Add và Sub.
Phương thức Add nhận một giá trị time.Duration và trả về một giá trị time.Time mới, biểu thị thời điểm ban đầu cộng với khoảng thời gian đó:
now := time.Now()
tomorrow := now.Add(24 * time.Hour)
fmt.Println(tomorrow)Phương thức Sub hoạt động theo hai cách. Khi bạn lấy một time.Time trừ một time.Time khác, phương thức trả về một time.Duration biểu thị khoảng chênh lệch giữa chúng:
start := time.Now()
end := start.Add(2 * time.Hour)
difference := end.Sub(start) // Trả về 2h0m0sCác phương thức này giúp bạn dễ dàng tính thời hạn, đo thời gian đã trôi qua hoặc lên lịch cho các sự kiện trong tương lai. Đối tượng time.Time ban đầu vẫn không thay đổi, cả hai phương thức đều trả về giá trị mới, phù hợp với cách Go ưu tiên các thao tác bất biến.
Thử thách
DễTạo một bộ tính thời hạn dự án dùng phép tính thời gian để xác định các cột mốc và thời hạn của dự án. Thử thách này sẽ kiểm tra khả năng sử dụng các phương thức Add và Sub trên các đối tượng time.Time để tính ngày trong tương lai và khoảng thời gian giữa các sự kiện.
Bạn sẽ nhận hai đầu vào:
- Một chuỗi chứa thông tin thời điểm bắt đầu dự án theo định dạng
"year:month:day:hour:minute"(ví dụ:"2024:1:15:9:0") - Một chuỗi chứa thời lượng các công việc theo định dạng
"task1:duration_value:duration_unit,task2:duration_value:duration_unit"(ví dụ:"Planning:5:Day,Development:3:Week,Testing:10:Day")
Nhiệm vụ của bạn:
- Phân tích đầu vào thứ nhất bằng cách tách chuỗi tại dấu hai chấm để lấy các giá trị năm, tháng, ngày, giờ và phút
- Chuyển các giá trị chuỗi này thành số nguyên và tạo thời điểm bắt đầu dự án bằng
time.Date(dùngtime.UTClàm múi giờ, đặt giây và nano giây thành 0) - Phân tích đầu vào thứ hai bằng cách tách chuỗi tại dấu phẩy để lấy từng mục công việc
- Với mỗi mục công việc, tách chuỗi tại dấu hai chấm để lấy tên công việc, giá trị thời lượng và đơn vị thời lượng
- Chuyển giá trị thời lượng thành số nguyên và tạo các đối tượng
time.Durationbằng các hằng số phù hợp:- Với
"Day": nhân với24 * time.Hour - Với
"Week": nhân với7 * 24 * time.Hour - Với
"Hour": nhân vớitime.Hour
- Với
- Hiển thị tiêu đề ứng dụng:
"=== PROJECT DEADLINE CALCULATOR ===" - Hiển thị thời điểm bắt đầu dự án:
"Project start time: [start_time_object]" - Tính thời hạn của từng công việc bằng cách cộng thời lượng của công việc đó vào thời điểm kết thúc công việc trước đó (công việc đầu tiên bắt đầu tại thời điểm bắt đầu dự án):
- Với mỗi công việc, hiển thị:
"Task: [task_name]"" Duration: [duration_object]"" Start: [task_start_time]"" End: [task_end_time]"(tính bằng phương thứcAdd)
- Tính và hiển thị tiến độ dự án:
"=== PROJECT TIMELINE ===""Project start: [start_time_object]""Project end: [final_task_end_time]""Total project duration: [total_duration_object]"(tính bằng phương thứcSubgiữa thời điểm kết thúc và thời điểm bắt đầu dự án)
- Hiển thị phân tích công việc:
"=== TASK ANALYSIS ===""Number of tasks: [number_of_tasks]""Longest task: [longest_task_name] ([longest_duration_object])""Shortest task: [shortest_task_name] ([shortest_duration_object])"
- Tính khoảng thời gian giữa các công việc liên tiếp và hiển thị khoảng trống:
"=== TASK TRANSITIONS ==="- Với mỗi cặp công việc liên tiếp:
"[first_task_name] to [second_task_name]: [time_difference_object]"(kết quả phải là 0 vì các công việc diễn ra liên tiếp)
- Hiển thị thống kê dự án:
"=== 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"
- Hiển thị thông báo hoàn tất:
"Project timeline calculation completed successfully"
Dùng gói time cho các thao tác thời gian, gói strings để tách chuỗi đầu vào, gói strconv để chuyển chuỗi thành số nguyên và gói fmt để định dạng đầu ra. Hãy nhớ rằng phương thức Add trả về một đối tượng time.Time mới, biểu thị thời điểm ban đầu cộng với thời lượng, còn phương thức Sub trả về một giá trị time.Duration, biểu thị khoảng chênh lệch giữa hai thời điểm. Thử thách này minh họa cách tạo tiến độ dự án hoàn chỉnh bằng các phép tính thời gian.
Tự làm thử
package main
import (
"fmt"
"strconv"
"strings"
"time"
)
func main() {
// Đọc đầu vào
var startInfo string
var taskInfo string
fmt.Scanln(&startInfo)
fmt.Scanln(&taskInfo)
// Phân tích thông tin thời gian bắt đầu
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])
// Tạo thời gian bắt đầu dự án
startTime := time.Date(year, time.Month(month), day, hour, minute, 0, 0, time.UTC)
// Phân tích thông tin công việc
taskEntries := strings.Split(taskInfo, ",")
// TODO: Viết code bên dưới
// - Xử lý từng mục công việc để lấy tên, giá trị thời lượng và đơn vị
// - Tạo đối tượng thời lượng cho từng công việc
// - Tính thời gian bắt đầu và kết thúc của từng công việc
// - Tìm công việc dài nhất và ngắn nhất
// - Tính số liệu thống kê của dự án
// - Hiển thị tất cả các phần đầu ra cần thiết
// Đoạn code bạn viết ở trên sẽ tạo ra đầu ra
}Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Logic và luồng điều khiển
1Luồng điều khiển nâng cao
Switch với `fallthrough`Thoát khỏi vòng lặp lồng nhauTiếp tục một vòng lặp cụ thểCâu lệnh `goto`Ôn tập: điều khiển vòng lặp nâng cao4Dự án: Danh sách việc cần làm đơn giản
Thiết lập dự ánThêm một việc cần làm7Xử lý lỗi chuyên sâu
Kiểu lỗi tùy chỉnhBọc lỗi bằng `%w`Gỡ bọc lỗi bằng `errors.Is`Gỡ bọc lỗi bằng `errors.As`Tìm hiểu `panic`Sử dụng `recover`Ôn tập: phép chia an toàn10Làm việc với thời gian
Lấy thời gian hiện tạiTạo thời điểm cụ thểĐịnh dạng thời gianPhân tích chuỗi thời gianKhoảng thời gianPhép tính thời gianTạm dừng và bộ đánh dấu thời gianÔn tập: Bộ hẹn giờ đơn giản2Struct và phương thức
Định nghĩa phương thức cho structReceiver giá trịReceiver con trỏChọn receiverPhương thức và hàmÔn tập: hành vi của struct5Tìm hiểu chuyên sâu về map
Map chứa structCon trỏ làm giá trị của mapKiểm tra map nilSo sánh các mapÔn tập: bộ đếm tần suất từ8Dự án: Quản lý hàng tồn kho đơn giản
Tổng quan dự ánKiểm tra hàng tồn kho3Interface (cơ bản)
Interface là gì?Định nghĩa interfaceTriển khai interfaceDùng kiểu interfaceInterface rỗngKhẳng định kiểuType switchÔn tập: hình dạng và hành viTự luyện tập: Trình biên dịch Go online