CodeGym /Các khóa học /C# SELF /Tính toán và các class hỗ trợ cho ngày và thời gian

Tính toán và các class hỗ trợ cho ngày và thời gian

C# SELF
Mức độ , Bài học
Có sẵn

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#.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ả
Days
Số ngày nguyên
Hours
Phần giờ
Minutes
Phần phút
Seconds
Phần giây
TotalDays
Thời gian tính bằng ngày (số thực)
TotalHours
Thời gian tính bằng giờ (số thực)
TotalMinutes
Thời gian tính bằng phút (số thực)
TotalSeconds
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)
AddDays(double)
Ngày (hỗ trợ số thực, ví dụ 1,5 ngày)
AddMonths(int)
Tháng (tự động tính số ngày trong tháng)
AddYears(int)
Năm (có tính năm nhuận)
AddHours(double)
Giờ
AddMinutes(double)
Phút
AddSeconds(double)
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
TimeSpan duration = d2 - d1
(d2 - d1).Days
Cộng 2 tuần vào ngày
date.AddDays(14)
date.AddDays(14)
Tính tuổi Công thức với
.Year
và kiểm tra tháng/ngày
Xem phần trên
Lấy/chỉ đặt ngày
DateOnly
DateOnly.FromDateTime(DateTime.Now)
Lấy/chỉ đặt thời gian
TimeOnly
TimeOnly.FromDateTime(DateTime.Now)
So sánh ngày Toán tử
<
,
>
,
==
,
.CompareTo()
if (d1 < d2) ...
Chuyển sang múi giờ khác
DateTimeOffset + ToOffset
dto.ToOffset(TimeSpan.FromHours(3))
Biết số tuần trong năm
Calendar.GetWeekOfYear()
xem tài liệu
Biết thứ trong tuần
date.DayOfWeek
Đếm số ngày làm việc Vòng lặp kiểm tra
DayOfWeek
Xem phần trên
1
Khảo sát/đố vui
, cấp độ , bài học
Không có sẵn
Làm việc với ngày tháng
Làm việc với ngày tháng, thời gian và múi giờ
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION