1. Những bài toán cơ bản khi làm việc với ngày và thời gian
Làm việc với ngày tháng và thời gian thường khiến dev cảm thấy hơi hoang mang (hoặc rất hoang mang), kể cả mấy bạn đã có kinh nghiệm. Sẽ phải so sánh ngày, tính khoảng cách, cộng/trừ ngày/tháng/năm, tính tuổi, xác định thứ trong tuần và nhiều thứ khác nữa.
Tất cả những thứ này là bài toán quen thuộc cho task tracker, lịch, quản lý thẻ/thành viên, tính toán tài chính, báo cáo thống kê, và tất nhiên là mấy bài phỏng vấn (kiểu như "tính số ngày làm việc giữa hai ngày").
Trong C# và .NET có sẵn các class và method cho mấy việc này. Quan trọng nhất là: hầu hết các phép tính đều làm qua API hướng đối tượng, an toàn và dễ hiểu.
2. Struct TimeSpan — đo khoảng thời gian
Mọi thứ bắt đầu với struct TimeSpan. Đây là "một đoạn" thời gian: ví dụ, 5 ngày, 3 tiếng, 7 phút và 21 giây.
Làm sao tạo TimeSpan?
Có thể "trừ" hai ngày, hoặc tạo trực tiếp:
// Chênh lệch giữa hai ngày luôn là TimeSpan!
DateTime start = new DateTime(2025, 5, 1, 7, 0, 0);
DateTime end = new DateTime(2025, 5, 2, 11, 30, 0);
TimeSpan duration = end - start; // Ma thuật thực sự!
Console.WriteLine(duration); // 1.04:30:00 (1 ngày, 4 tiếng, 30 phút)
Có thể tạo TimeSpan qua constructor với tham số:
TimeSpan span = new TimeSpan(2, 14, 18, 0); // 2 ngày, 14 tiếng, 18 phút, 0 giây
Console.WriteLine(span); // 2.14:18:00
Cách khác là dùng static method, thường dễ đọc hơn:
TimeSpan fiveMinutes = TimeSpan.FromMinutes(5);
TimeSpan twoHours = TimeSpan.FromHours(2);
TimeSpan oneWeek = TimeSpan.FromDays(7);
TimeSpan có những thuộc tính gì?
| Thuộc tính | Mô tả |
|---|---|
|
Số ngày nguyên |
|
Phần giờ |
|
Phần phút |
|
Phần giây |
|
Thời gian tính bằng ngày (số thực) |
|
Thời gian tính bằng giờ (số thực) |
|
Thời gian tính bằng phút (số thực) |
|
Thời gian tính bằng giây (số thực) |
Console.WriteLine($"Ngày: {duration.Days}, Tổng số giờ: {duration.TotalHours}");
Làm sao cộng/trừ TimeSpan vào ngày?
DateTime now = DateTime.Now;
DateTime future = now.Add(duration); // Cộng duration vào now
DateTime past = now.Subtract(TimeSpan.FromDays(10)); // Trừ 10 ngày
Console.WriteLine(future);
Console.WriteLine(past);
3. Máy tính ngày: tính chênh lệch giữa các ngày
Kỹ năng này gần như lúc nào cũng cần. Ví dụ, ai đó muốn biết còn bao lâu nữa đến kỳ nghỉ, hoặc khi nào hết thời gian dùng thử miễn phí.
DateTime today = DateTime.Today;
DateTime vacation = new DateTime(2025, 8, 1);
TimeSpan untilVacation = vacation - today;
Console.WriteLine($"Còn {untilVacation.Days} ngày nữa đến kỳ nghỉ!");
Lưu ý: nếu trừ hai "ngày" không có thời gian (dùng DateTime.Date hoặc DateTime.Today), kết quả luôn là số ngày nguyên. Nếu một trong hai có thời gian, kết quả sẽ là số thực.
int days = (vacation - today).TotalDays; // Lỗi biên dịch! TotalDays là double
Nếu cần số nguyên — dùng .Days hoặc ép kiểu về int qua (int)TotalDays.
4. Cộng/trừ thời gian: các method AddDays, AddMonths, AddHours, ...
C# không bắt bạn phải tự tính số ngày trong tháng, năm nhuận hay mấy thứ đau đầu khác. Chỉ cần dùng:
DateTime orderDate = new DateTime(2024, 4, 20);
DateTime deliveryDate = orderDate.AddDays(14); // Sau 2 tuần
Console.WriteLine($"Hàng sẽ được giao vào {deliveryDate.ToShortDateString()}");
| Method | Cộng gì (hoặc trừ nếu số âm) |
|---|---|
|
Ngày (hỗ trợ số thực, ví dụ 1,5 ngày) |
|
Tháng (tự động tính số ngày trong tháng) |
|
Năm (có tính năm nhuận) |
|
Giờ |
|
Phút |
|
Giây |
DateTime birthday = new DateTime(2000, 2, 29);
DateTime nextYear = birthday.AddYears(1); // 2001-02-28 (không phải 29, vì 2001 không nhuận)
Console.WriteLine(nextYear.ToShortDateString()); // 28.02.2001
Đừng quên: tất cả các method này trả về một instance ngày mới, ngày gốc không đổi!
var dt = DateTime.Now;
dt.AddDays(5); // KHÔNG thay đổi dt!
dt = dt.AddDays(5); // Bây giờ mới thay đổi
5. Các method hỗ trợ cho tính toán
Tính thứ trong tuần
Thường thì chỉ cần dùng thuộc tính .DayOfWeek:
DateTime examDate = new DateTime(2025, 6, 19);
DayOfWeek day = examDate.DayOfWeek;
Console.WriteLine(day); // Wednesday
Có thể ép về số nguyên:
int number = (int)day; // Sunday == 0, Monday == 1, v.v.
Kiểm tra "hôm nay", "hôm qua", "ngày mai"
So sánh đơn giản:
DateTime date = new DateTime(2025, 6, 18);
if (date.Date == DateTime.Today)
Console.WriteLine("Hôm nay!");
else if (date.Date == DateTime.Today.AddDays(-1))
Console.WriteLine("Hôm qua!");
else if (date.Date == DateTime.Today.AddDays(1))
Console.WriteLine("Ngày mai!");
Tính tuổi
Một trong những bài toán phổ biến nhất — tính tuổi người cho chuẩn. Trừ năm đơn giản không phải lúc nào cũng đúng:
public static int CalculateAge(DateTime birthDate, DateTime currentDate)
{
int age = currentDate.Year - birthDate.Year;
// Nếu sinh nhật chưa đến trong năm nay
if (currentDate.Month < birthDate.Month ||
(currentDate.Month == birthDate.Month && currentDate.Day < birthDate.Day))
{
age--;
}
return age;
}
// Sử dụng
DateTime birth = new DateTime(1990, 8, 15);
DateTime today = DateTime.Today;
int age = CalculateAge(birth, today);
Console.WriteLine($"Tuổi: {age} năm");
Làm việc với ngày làm việc
Thường cần tính số ngày làm việc giữa hai ngày, loại trừ cuối tuần:
public static int CountWorkingDays(DateTime startDate, DateTime endDate)
{
int workingDays = 0;
DateTime current = startDate;
while (current <= endDate)
{
if (current.DayOfWeek != DayOfWeek.Saturday &&
current.DayOfWeek != DayOfWeek.Sunday)
{
workingDays++;
}
current = current.AddDays(1);
}
return workingDays;
}
6. Các class chính liên quan với nhau như thế nào
graph TD
A(DateTime) --tru--> B(TimeSpan)
A2(DateTime) --AddDays, AddMonths--> A
A --ToLocalTime/ToUniversalTime--> C(DateTimeOffset)
D(DateOnly) --ToDateTime--> A
E(TimeOnly) --ToTimeSpan--> B
A --DayOfWeek, Day, Month, Year--> F(Thuộc tính số)
B(TimeSpan) --TotalDays, TotalHours, ...--> G(Thuộc tính độ dài)
7. "Sổ tay" nhanh: làm gì nếu...
| Bài toán | Dùng gì | Ví dụ |
|---|---|---|
| Biết chênh lệch giữa hai ngày | |
|
| Cộng 2 tuần vào ngày | |
|
| Tính tuổi | Công thức với và kiểm tra tháng/ngày |
Xem phần trên |
| Lấy/chỉ đặt ngày | |
|
| Lấy/chỉ đặt thời gian | |
|
| So sánh ngày | Toán tử , , , |
|
| Chuyển sang múi giờ khác | |
|
| Biết số tuần trong năm | |
xem tài liệu |
| Biết thứ trong tuần | |
|
| Đếm số ngày làm việc | Vòng lặp kiểm tra |
Xem phần trên |
GO TO FULL VERSION