TuViChinhXac.comTử Vi Chính Xác
Đổi dương lịch – âm lịch cho lá số

Viết hàm đổi âm lịch cho công cụ lá số: tham số múi giờ, ngày kiểm thử, lỗi biên

Cho người viết công cụ lá số: các bước của hàm đổi âm lịch, vì sao múi giờ phải là tham số, mười hai ngày kiểm thử đã tự kiểm và những lỗi biên hay lọt.

A developer seen from behind at a small desk in a Ho Chi Minh City apartment at night, laptop screen dark and blank, notebook with empty grid, warm desk lamp

Một hàm đổi âm lịch dùng cho công cụ lập lá số cần ba thứ: thuật toán tính ngày sóc và trung khí theo một múi giờ truyền vào làm tham số (UTC+7 cho lịch Việt), cách xử lý tháng nhuận được trả ra rõ ràng thay vì gộp vào số tháng, và một bộ ngày kiểm thử phủ các ca biên như Tết 1985, Tết Mậu Thân 1968, tháng nhuận, tháng Chạp vắt sang năm dương sau. Thiếu một trong ba, công cụ sẽ cho kết quả đúng ở hầu hết ngày nhưng sai đúng ở những ca mà người dùng hay hỏi nhất.

Bài này viết cho người lập trình và người kiểm thử công cụ lá số, ở mức mô tả và mã giả bằng chữ, không đưa mã nguồn dài. Mọi ngày trong bộ kiểm thử đã được tính lại bằng thuật toán điểm sóc, trung khí với hai múi giờ. Một công cụ đổi lịch đúng chỉ bảo đảm dữ liệu vào lá số đúng; nó không biến lời luận trên lá số thành điều có bằng chứng, và giao diện công cụ cũng không nên ngụ ý như vậy.

Các bước của hàm đổi dương sang âm

Phần lớn các cài đặt hiện nay đi theo cùng một khung, dựa trên công thức thiên văn gần đúng cho thời điểm điểm sóc và kinh độ mặt trời. Mô tả bằng chữ như sau.

  1. Đổi ngày dương lịch sang số ngày Julius (một số nguyên đếm ngày liên tục). Mọi phép so sánh ngày sau đó làm trên số này.
  2. Tìm điểm sóc gần nhất trước hoặc bằng ngày cần đổi. Thời điểm điểm sóc tính theo giờ quốc tế, rồi cộng múi giờ và lấy phần nguyên để ra ngày sóc theo lịch địa phương. Ngày sóc là mùng Một.
  3. Tìm tháng Mười Một của năm: tháng âm chứa điểm Đông chí. Làm việc này cho năm hiện tại và năm trước (hoặc năm sau) để có hai mốc tháng Mười Một bao quanh ngày cần đổi.
  4. Nếu giữa hai tháng Mười Một có mười ba lần sóc, năm đó có tháng nhuận. Tháng nhuận là tháng đầu tiên sau tháng Mười Một mà trong tháng không có trung khí nào.
  5. Đánh số tháng từ mốc tháng Mười Một, bỏ qua tháng nhuận khi tăng số, và gắn cờ nhuận cho tháng đó.
  6. Ngày âm là số ngày từ mùng Một tới ngày cần đổi, cộng một. Năm âm lịch là năm của tháng Giêng tương ứng; tháng Mười Một và tháng Chạp thuộc năm âm trước nếu ngày dương đã sang năm mới.

Hàm ngược (âm sang dương) đi theo chiều ngược lại: từ năm âm tìm mốc tháng Mười Một, đếm tới tháng cần tìm (lưu ý tháng nhuận), lấy ngày sóc rồi cộng số ngày. Hàm ngược phải từ chối các đầu vào không tồn tại, như cờ nhuận cho tháng không nhuận hay ngày 30 của tháng thiếu.

Múi giờ là tham số, không phải hằng số ẩn

Lịch Việt và lịch Trung Quốc dùng cùng thuật toán, chỉ khác múi giờ: UTC+7 và UTC+8. Nếu múi giờ được viết cứng trong hàm, công cụ của bạn chỉ phục vụ được một lịch. Nếu nó là tham số, bạn có thể cho người dùng chọn, hoặc tự chọn theo nơi sinh và năm sinh, và quan trọng hơn là viết được kiểm thử so sánh hai lịch.

Có hai lý do thực tế để cần UTC+8 ngay cả trong công cụ cho người Việt. Thứ nhất, theo các tài liệu lịch pháp thường dẫn, âm lịch ở miền Bắc trước 1968 và ở miền Nam trước 1975 tính theo UTC+8; người dùng sinh trong các giai đoạn đó có thể muốn lá số theo lịch gia đình đã dùng. Thứ hai, người dùng hay mang lá số từ sách hay nguồn nước ngoài tới so, và công cụ cần giải thích được vì sao hai bên khác.

Một lỗi phổ biến khác là múi giờ bị "rò" từ môi trường chạy: hàm dùng đối tượng ngày giờ của ngôn ngữ lập trình, đối tượng này tự áp múi giờ của máy chủ hoặc trình duyệt. Một người dùng ở Mỹ mở trang, ngày sinh nhập vào bị chuyển sang ngày hôm trước trước khi tới hàm đổi lịch. Cách tránh: chuyển ngày nhập thành bộ ba số nguyên ngày, tháng, năm ngay từ đầu và chỉ làm việc trên số ngày Julius, không để đối tượng ngày giờ của hệ thống chạm vào.

Bộ ngày kiểm thử tối thiểu

Bảng dưới gồm những ngày đã được tính lại theo cả hai múi giờ. Một hàm đổi lịch Việt đúng phải cho đúng cột UTC+7; nếu hàm nhận múi giờ làm tham số, cột UTC+8 kiểm luôn nhánh đó.

Ngày dươngKết quả UTC+7 (lịch Việt)Kết quả UTC+8Kiểm điều gì
10/02/2024Mùng 1 tháng Giêng Giáp ThìnNhư UTC+7Tết thường; can chi ngày Giáp Thìn
06/02/2027Mùng 1 tháng Giêng Đinh MùiNhư UTC+7Tết năm tới
22/03/2023Mùng 1 tháng Hai nhuận Quý MãoNhư UTC+7Cờ nhuận
25/07/2025Mùng 1 tháng Sáu nhuận Ất TỵNhư UTC+7Cờ nhuận giữa năm
01/01/2000Ngày 25 tháng Mười Một Kỷ MãoNhư UTC+7Năm âm của tháng Mười Một; can chi ngày Mậu Ngọ
10/01/1971Ngày 14 tháng Chạp Canh TuấtNhư UTC+7Tháng Chạp vắt sang năm dương sau
05/02/1985Ngày 16 tháng Giêng Ất SửuNgày 16 tháng Chạp Giáp TýLệch năm do tháng nhuận đặt khác chỗ
25/03/1985Ngày 5 tháng Hai nhuận Ất SửuNgày 5 tháng Hai Ất SửuTháng nhuận chỉ có ở một bên
29/01/1968Mùng 1 tháng Giêng Mậu ThânNgày 30 tháng Chạp Đinh MùiĐiểm sóc sát nửa đêm
17/02/2007Mùng 1 tháng Giêng Đinh HợiNgày 30 tháng Chạp Bính TuấtLệch Tết một ngày
14/12/2020Mùng 1 tháng Mười Một Canh TýNgày 30 tháng Mười Canh TýLệch đầu tháng
15/12/2020Ngày 2 tháng Mười Một Canh TýMùng 1 tháng Mười Một Canh TýNgày kế tiếp vẫn lệch

Với hàm ngược, thêm ba ca: ngày 10 tháng Tư năm Giáp Thân (không nhuận) phải ra 02/05/1944; ngày 10 tháng Tư nhuận năm Giáp Thân phải ra 31/05/1944; ngày 30 tháng Tư năm Giáp Thân không nhuận phải bị từ chối, vì tháng đó chỉ có 29 ngày.

Bộ này nhỏ nhưng phủ đủ các nhánh của thuật toán. Nên chạy nó trong mọi lần sửa mã, và thêm vào bất kỳ ngày nào người dùng từng báo sai.

Kiểm thử theo tính chất trên cả dải năm

Bộ ngày cố định bắt được lỗi ở các ca đã biết. Để bắt lỗi ở những ca chưa ai nghĩ tới, hãy chạy thêm các phép kiểm theo tính chất trên mọi ngày của một dải dài, ví dụ 1900 – 2100. Các tính chất dưới đây phải đúng với mọi lịch âm dương tính đúng quy tắc.

  • Đổi đi rồi đổi về: mọi ngày dương đổi sang âm (kèm cờ nhuận) rồi đổi ngược phải ra đúng ngày ban đầu.
  • Độ dài tháng: mọi tháng âm dài đúng 29 hoặc 30 ngày, không có tháng 28 hay 31 ngày.
  • Số tháng trong năm: mỗi năm âm có 12 tháng, hoặc 13 tháng nếu có đúng một tháng nhuận; không năm nào có hai tháng nhuận.
  • Tháng Mười Một chứa Đông chí: với mọi năm, tháng gắn số 11 (không nhuận) phải chứa ngày Đông chí.
  • Tết nằm trong khoảng hợp lý: ngày mùng Một tháng Giêng luôn rơi trong khoảng từ khoảng 21/01 đến 20/02 dương lịch.
  • Can chi ngày liên tục: hai ngày dương liên tiếp có can chi cách nhau đúng một bước trong vòng sáu mươi.

Mỗi tính chất là vài dòng mã, chạy hết dải hai trăm năm trong vài giây. Khi một tính chất bị vi phạm, in ra ngày đầu tiên vi phạm; thường đó là một lỗi lấy phần nguyên, một lỗi chỉ số tháng nhuận hay một lỗi ở ranh giới năm.

Riêng phép kiểm so hai múi giờ: chạy cả dải với UTC+7 và UTC+8, liệt kê các tháng khác nhau. Danh sách đó vừa là dữ liệu kiểm thử, vừa là thông tin hữu ích để hiển thị dòng nhắc cho người dùng sinh vào những tháng ấy.

Những lỗi biên hay lọt qua

Lấy tròn thay vì lấy phần nguyên. Ngày sóc phải là phần nguyên của thời điểm sóc theo giờ địa phương. Dùng phép làm tròn sẽ dời mọi điểm sóc sau 12 giờ trưa sang ngày hôm sau, làm lệch cả tháng.

Mất cờ nhuận ở giao diện. Hàm trả về cờ nhuận nhưng giao diện chỉ hiện "tháng 2", hoặc khi lưu vào cơ sở dữ liệu chỉ lưu số tháng. Lá số sau đó không biết đây là tháng nhuận, và quy ước tháng nhuận của người dùng không được áp.

Năm âm của tháng Mười Một, tháng Chạp. Ngày 01/01/2000 thuộc năm Kỷ Mão chứ không phải Canh Thìn. Hàm nào gán năm âm bằng năm dương cho mọi ngày trước Tết sẽ sai ở đây.

Ngày hợp lệ ở hàm ngược. Hàm ngược nhận "30 tháng Tư" mà không kiểm tháng đó thiếu sẽ âm thầm trả về mùng Một tháng sau. Người dùng không biết mình vừa nhập một ngày không tồn tại.

Sai số của công thức gần đúng. Công thức thiên văn rút gọn có sai số cỡ vài phút. Khi điểm sóc hay trung khí rơi chỉ cách nửa đêm vài phút, kết quả có thể lệch một ngày so với lịch chính thức. Nên đánh dấu những ngày như vậy và đối chiếu với lịch đã công bố.

Giờ Tý không phải việc của hàm đổi lịch. Chuyện người sinh sau 23 giờ tính sang ngày hôm sau hay không là quy ước của tử vi, nên xử lý ở tầng lập lá số, có tuỳ chọn rõ ràng, chứ không nhét vào hàm đổi lịch.

Hiển thị cho người dùng: để họ tự kiểm được

Một công cụ lá số có trách nhiệm nên hiển thị ngay sau khi nhập: ngày âm lịch đã đổi (có chữ "nhuận" nếu có), năm can chi, can chi ngày, và lịch đã dùng (UTC+7 hay UTC+8). Người dùng nhìn dòng này là kiểm được với ký ức gia đình hoặc tờ lịch cũ, trước khi đọc bất cứ ô nào khác.

Với những ca biên đã biết, như người sinh trong khoảng 23/11/1984 – 19/4/1985, người sinh trong tháng có điểm sóc sát nửa đêm, hay người sinh ở miền Nam trước 1975, công cụ có thể hiện một dòng nhắc: ngày này hai lịch cho kết quả khác nhau, kèm cả hai kết quả. Dòng nhắc ngắn này tiết kiệm cho người dùng nhiều lần thắc mắc vì sao lá số khác nơi khác.

Cuối cùng, công cụ không nên dùng chữ "chính xác" theo nghĩa tiên đoán. Đổi lịch đúng và an sao đúng quy tắc là chính xác về dữ liệu; còn nội dung luận giải là chuyện khác, và giao diện nên tách hai phần đó ra. Nếu bạn muốn so kết quả với một công cụ sẵn có, có thể lập lá số trên AI Huyền Học rồi chạy bộ ngày kiểm thử ở trên với cả hai.

Câu hỏi thường gặp

Có cần tự viết thuật toán âm lịch không, hay dùng bảng tra sẵn?

Bảng tra sẵn tiện nhưng chỉ phủ một khoảng năm và có thể mang lỗi chép. Thuật toán tính từ điểm sóc, trung khí phủ được mọi năm và cho phép đổi múi giờ. Dù chọn cách nào, bộ ngày kiểm thử vẫn là bắt buộc.

Vì sao phải hỗ trợ UTC+8 cho người dùng Việt?

Vì theo các tài liệu lịch pháp, âm lịch ở miền Bắc trước 1968 và ở miền Nam trước 1975 tính theo UTC+8, và nhiều lá số từ sách, nguồn nước ngoài cũng theo lịch này. Có tham số múi giờ, công cụ giải thích được vì sao hai kết quả khác nhau.

Ngày kiểm thử nào bắt được nhiều lỗi nhất?

Ngày 05/02/1985 rất hiệu quả: lịch Việt cho ngày 16 tháng Giêng Ất Sửu, lịch Trung Quốc cho ngày 16 tháng Chạp Giáp Tý. Thêm 01/01/2000 để kiểm năm âm của tháng Mười Một và 22/03/2023 để kiểm cờ nhuận.

Sai số của công thức thiên văn gần đúng có đáng lo không?

Với hầu hết các ngày thì không, vì điểm sóc cách nửa đêm rất xa. Chỉ những tháng có điểm sóc hoặc trung khí cách nửa đêm vài phút mới có nguy cơ lệch. Nên đánh dấu những tháng này và đối chiếu với lịch đã công bố.

Có nên xử lý giờ Tý trong hàm đổi lịch không?

Không nên. Hàm đổi lịch chỉ đổi một ngày dương sang ngày âm. Việc người sinh sau 23 giờ có tính sang ngày hôm sau hay không là quy ước của người lập lá số, nên đặt ở tầng lá số với tuỳ chọn rõ ràng.

Đổi lịch đúng thì công cụ có thể quảng bá là xem tử vi chính xác không?

Không nên. Đổi lịch đúng và an sao đúng quy tắc chỉ là chính xác về dữ liệu. Lời luận trên lá số chưa có bằng chứng về giá trị dự đoán, và giao diện nên nói rõ điều đó thay vì gộp hai thứ vào một chữ "chính xác".

Cần tư vấn cụ thể cho trường hợp của bạn?

Chúng tôi sẽ liên hệ trong vòng 24 giờ.

Đăng ký tư vấn ngay

Bài viết liên quan

Bạn cần hỗ trợ thêm?

Để lại thông tin, chúng tôi sẽ liên hệ trong 24 giờ.

hoặc
Gọi ngay 0926.183.183