Thứ Ba, 19 tháng 1, 2016

Điều kỳ diệu của đối tượng Date trong Javascript

Lần này mình xin "đổi gió" chút đỉnh. Hôm nay mình xin trình bày về đối tượng Date trong Javascript. Ngày tháng là yếu tố quan trọng, được sử dụng khá nhiều, nên việc tính toán ngày tháng cũng muôn hình vạn trạng.

Khởi tạo một đối tượng Date
var now = new Date();
Với lệnh khởi tạo Date không tham số, hệ thống sẽ trả về ngày hiện tại. Ta cũng có thể khởi tạo đối tượng Date bằng cách chỉ định rõ những tham số theo thứ tự sau: năm, tháng, ngày, giờ, phút, giây:
var vnwomanDay = new Date(2010, 9, 20);
alert(vnwomanDay);
var vnwomanDayAndTime = new Date(2010, 9, 20, 12, 20, 30);
alert(vnwomanDayAndTime);


Có một điểm cần lưu ý, trong Javascript, tháng được tính từ 0 - 11, nghĩa là 0 là tháng 1, 1 là tháng 2 ... Chúng ta phải luôn ghi nhớ điều này để tránh tính toán hoặc hiển thị nhầm.


Date còn được khởi tạo bằng cách truyền vào một chuỗi ngày tháng hợp lệ
var date1 = new Date("10/20/2010");
alert(date1);
var date2 = new Date("Wednesday, October 20, 2010");
alert(date1);


Cả 2 kết quả đều như nhau, chỉ khác nội dung chuỗi tham số khởi tạo. Tháng trình bày trong chuỗi vẫn tính từ 1 - 12, không cần phải chuyển đổi thành 0 - 11 như truyền trực tiếp tham số tháng ở trên. Nhưng nếu ta sử dụng chuỗi làm tham số khởi tạo mà lại bỏ quên chữ new, kết quả sẽ không như mong đợi
var dateValue = new Date("10/20/2010");
alert(typeof(dateValue));
var stringValue = Date("10/20/2010");
alert(typeof(stringValue));


Lệnh khởi tạo ở dòng 1 sẽ trả về đối tượng Date chính hiệu, ta có thể truy xuất những hàm getDate, getMonth trên chính đối tượng này, riêng lệnh ở dòng 3 sẽ trả về chuỗi thay vì đối tượng Date như mong đợi, điều này chỉ đáp ứng được việc hiển thị và chúng ta không thể truy xuất những phương thức của Date "chính hiệu". Tham khảo thêm thông tin và cách sử dụng những phương thức của đối tượng Date tại http://w3schools.com/js/js_obj_date.asp

Date trong Javascript thật tuyệt vời
Ở một số ngôn ngữ lập trình, đối tượng Date khi sử dụng có sự ràng buộc chặt chẽ về thông tin nhập, xuất, khởi tạo, nhưng trong Javascript, Date rất chi là thoải mái, mở rộng, ta có thể linh động hơn trong việc xử lý tính toán ngày tháng thật dễ dàng. Một số ví dụ
var now = new Date();
alert("Ngày hôm nay: " + now);
alert("Ngày hôm qua: " + new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1));
alert("Ngày mai: " + new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1));
alert("Ngày mốt: " + new Date(now.getFullYear(), now.getMonth(), now.getDate() + 2));
alert("Tháng trước: " + new Date(now.getFullYear(), now.getMonth() - 1, now.getDate()).getMonth() + 1); // phải cộng thêm 1 vì tháng tính từ 0 - 11
alert("Tháng sau: " + new Date(now.getFullYear(), now.getMonth() + 1, now.getDate()).getMonth() + 1); // phải cộng thêm 1 vì tháng tính từ 0 - 11


Như bạn thấy, để tìm ngày hôm trước, hôm sau ta không cần quan tâm gì cả, chỉ việc lấy thông tin năm, tháng hiện tại, và cộng hoặc trừ đi ngày hiện tại là ra đáp án, nếu phải tính toán theo lý thuyết thì chúng ta cần phải kiểm tra khá nhiều:
Ngày hôm nay có phải cuối tháng không, nếu phải thì tăng tháng lên 1, nếu không phải thì tăng ngày lên 1, muốn biết một ngày có phải cuối tháng hay không, ta phải biết được tháng đó có bao nhiêu ngày, muốn biết tháng có bao nhiêu ngày ta phải biết được tháng đó là tháng thường hay tháng nhuần của năm nhuần. Và khi tăng / giảm tháng đi 1, ta phải xác định tháng đó là đầu năm hay cuối năm, để tăng / giảm năm đi 1... Ôi, cả một mớ lý thuyết phải biết, phải kiểm tra, nhưng thật nhẹ nhàng với javascript, chỉ đơn giản 1 dòng lệnh đã có thể đạt được kết quả như mong muốn.

Tính khoảng thời gian
Khi xử lý tính toán, thường gặp nhất là việc kiểm tra xem khoảng cách thời gian từ mốc A đến mốc B là bao nhiêu, bằng đoạn mã sau ta có thể tính dễ dàng được từ đây đến Noel còn bao nhiêu ngày, bao nhiêu giờ, bao nhiêu phút, bao nhiêu giây
var now = new Date();
var xmasDay = new Date(now.getFullYear(), 11, 24); // khởi tạo ngày Noel cùng năm với ngày hiện tại
var offset = xmasDay.getTime() - now.getTime(); // lấy độ lệch của 2 mốc thời gian, đơn vị tính là millisecond
var totalDays = Math.round(offset / 1000 / 60 / 60 / 24);
alert("Còn " + totalDays + " ngày là đến Noel");
var totalHours = Math.round(offset / 1000 / 60 / 60);
alert("Còn " + totalHours + " giờ là đến Noel");
var totalMinutes = Math.round(offset / 1000 / 60);
alert("Còn " + totalMinutes + " phút là đến Noel"); 
var totalSeconds = Math.round(offset / 1000);
alert("Còn " + totalSeconds + " giây là đến Noel"); 

// Tính chi tiết hơn
var days = Math.floor(offset / 1000 / 60 / 60 / 24);
offset -= days * 1000 * 60 * 60 * 24; // giảm offset đi
var hours = Math.floor(offset / 1000 / 60 / 60);
offset -= hours * 1000 * 60 * 60; // giảm offset đi
var minutes = Math.floor(offset / 1000 / 60);
offset -= minutes * 1000 * 60;
var seconds = Math.floor(offset / 1000);
alert("Còn " + days + " ngày " + hours + " giờ " + minutes + " phút " + seconds + " giây là đến Noel");


Đoạn mã trên sử dụng hàm getTime của Date, (tham khảo tại w3schools) hàm này trả về tổng số millisecond tính từ ngày 1/1/1970, chính vì vậy 2 ngày khác nhau nhưng cùng một mốc tính là 1/1/1970 chúng ta có thể tính toán ra được những thành phần khác. 

Xác định năm nhuần
Một nhu cầu cấp thiết khác đó là xác định một năm có phải là năm nhuần hay không, theo định nghĩa, năm nhuần là năm chia hết cho 100 và 400 (xem thêm tại Wiki), nhưng với Javascript ta chỉ cần
function isLeapYear(year) {
    return new Date(year, 2, 0).getDate() > 28;
}
alert("Năm 2000 là năm " + (isLeapYear(2000) ? "nhuần" : "thường"));
alert("Năm 2004 là năm " + (isLeapYear(2004) ? "nhuần" : "thường"));
var inputYear = prompt("Nhập năm cần xác định", new Date().getFullYear());
if(!isNaN(inputYear)) alert(isLeapYear(inputYear) ? "Năm nhuần" : "Năm thường");


Đoạn mã trên lấy ý tưởng xác định ngày cuối cùng của tháng 2 của năm cần tính có lớn hơn 28 hay không, nếu lớn hơn thì là năm nhuần, ngược lại thì không, mọi chuyện tính toán đều phó mặc cho "anh" javascript. Ý tưởng là thế nên để tính ngày cuối tháng 2 ta truyền vào là 2 (ở đây 2 chính là tháng 3 do tháng từ 0 - 11). Ngày 0 là như thế nào ? Ngày 1 là ngày đầu tháng, còn ngày 0 là ngày cuối cùng của của tháng đang tính, vậy ngày 0 của tháng 3 là ngày cuối cùng của tháng 2.

Tính số ngày của tháng
Từ ví dụ trên, ta có thể phát triển thành hàm tính số ngày của tháng dễ dàng
function getDaysOfMonth(year, month) {
    return new Date(year, month + 1, 0).getDate();
}
alert("Tháng 2 có " + getDaysOfMonth(new Date().getFullYear(), 1) + " ngày"); // tháng 2 có giá trị là 1
alert("Tháng 10 có " + getDaysOfMonth(new Date().getFullYear(), 9) + " ngày"); // tháng 10 có giá trị là 9


Xác định thứ tự ngày, tuần trong năm
Để xác định thứ tự một ngày trong năm, ý tưởng là sẽ lấy mốc thời gian hiện tại trừ đi mốc thời gian từ đầu năm, tương tự chúng ta cũng có thể tính được thứ tự tuần trong năm bằng cách lấy thứ tự ngày chia và làm tròn cho 7.
function getDayOfYear(date) {
    var offset = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 1).getTime();
    return Math.ceil(offset / 1000 / 60 / 60 / 24);
}

function getWeekOfYear(date) {
    var dayOfYear = getDayOfYear(date);
    return Math.ceil(dayOfYear / 7);
}
var now = new Date();
alert("Hôm nay là ngày thứ " + getDayOfYear(now) + " của năm.");
alert("Hôm nay là tuần thứ " + getWeekOfYear(now) + " của năm.");

0 nhận xét: