Day.js: thư viện thay thế Moment.js chỉ 2kB
Day.js xứng đáng với phép so sánh nó tự đặt ra với Moment.js: API gần như giữ nguyên nên kinh nghiệm cũ dùng được ngay, còn kích thước 2kB mới là lý do thật sự để chuyển sang. Vấn đề là README chỉ nói 'largely' tương thích chứ không phải giống hệt, nên khi migrate vẫn cần rà lại từng method thay vì tìm-và-thay-thế mù quáng. Với dự án mới hoàn toàn, đây là lựa chọn dễ dàng.
Day.js là gì?
Day.js là một thư viện JavaScript dùng để parse, validate, thao tác và định dạng ngày giờ, đóng gói chỉ trong 2kB với API tương thích phần lớn với Moment.js. Mỗi thao tác trả về một instance Day.js mới thay vì thay đổi instance gốc, còn các tính năng mở rộng như định dạng nâng cao được nạp qua plugin bằng dayjs.extend().
Các tính năng nổi bật của Day.js
- ✓Bất biến (immutable) theo thiết kế: các method như .add() hay .startOf() luôn trả về một instance Day.js mới thay vì sửa instance gốc.
- ✓Gọi method nối tiếp (chainable), ví dụ dayjs().startOf('month').add(1, 'day').format('YYYY-MM-DD HH:mm:ss').
- ✓Core chỉ 2kB.
- ✓File locale nạp theo yêu cầu — import 'dayjs/locale/es' rồi gọi dayjs.locale('es') thay vì đóng gói sẵn mọi ngôn ngữ.
- ✓Có hệ thống plugin cho các tính năng thêm như advancedFormat, chỉ được thêm vào khi gọi dayjs.extend().
- ✓API đủ gần với Moment.js để các thao tác parse, format, get/set, manipulate, query gần như dùng lại được ngay.
Cài đặt Day.js trong dự án
Cài Day.js chỉ cần một lệnh: npm install dayjs --save — đây là cách cài duy nhất được README nêu ra, không có lệnh yarn hay pnpm tương ứng. Sau đó chỉ cần import dayjs from 'dayjs' rồi gọi trực tiếp; README dẫn sang day.js.org để xem hướng dẫn cài đặt đầy đủ và API reference thay vì liệt kê hết trong README. Không thấy nhắc tới bước build hay file config riêng nào.
Parse, format và thao tác ngày giờ
Cách dùng Day.js đi theo đúng 5 động từ mà docs của nó liệt kê: parse, display, get & set, manipulate, và query. dayjs('2018-08-08') parse một chuỗi thành instance. dayjs().format('{YYYY} MM-DDTHH:mm:ss SSS [Z] A') format ngược lại ra chuỗi với token tuỳ chỉnh. dayjs().set('month', 3).month() vừa get vừa set một unit trong cùng một lệnh gọi. dayjs().add(1, 'year') manipulate bằng cách trả về instance mới, lùi hoặc tiến một năm. dayjs().isBefore(dayjs()) query, so sánh instance này với instance khác. Nối các thao tác này lại chính là ví dụ trong README: dayjs().startOf('month').add(1, 'day').set('year', 2018).format('YYYY-MM-DD HH:mm:ss').
Các trường hợp sử dụng phổ biến của Day.js
- •Định dạng và hiển thị ngày giờ trong UI mà không phải kéo theo một dependency ngày giờ nặng nề.
- •Thay thế Moment.js trong dự án hiện có, chủ yếu để giảm kích thước bundle.
- •Xây pipeline xử lý ngày giờ cần nối tiếp parse, manipulate, query, kiểu dayjs().startOf('month').add(1,'day').
- •Ứng dụng cần nhiều locale — chỉ nạp đúng locale đang dùng qua dayjs.locale().
- •Dự án muốn thêm tính năng định dạng dần dần về sau mà không làm phình bundle gốc, nhờ hệ thống plugin.
Điểm mạnh
- ✓API bất biến loại bỏ hẳn một nhóm bug do shared state mà instance mutable của Moment.js hay gây ra.
- ✓Chỉ 2kB, tính năng thêm chỉ được nạp khi bạn chủ động dùng plugin.
- ✓Tên method và cách gọi nối tiếp gần như giữ nguyên từ Moment.js, nên migrate chủ yếu là quen cú pháp cũ chứ không phải học thư viện mới.
- ✓Giấy phép MIT — dùng thương mại thoải mái, không vướng câu hỏi bản quyền.
- ✓Hỗ trợ i18n nạp theo từng locale khi cần, không đóng gói sẵn mọi ngôn ngữ.
Giới hạn của Day.js
- △README chỉ nói 'largely' tương thích với Moment.js, không phải giống hệt — migrate kiểu tìm-và-thay-thế thẳng vẫn có thể dính khác biệt về method hoặc cách format cần rà lại thủ công.
- △Bản cài gốc không có sẵn mọi tính năng; các plugin định dạng nâng cao như advancedFormat phải tự tìm và thêm riêng qua dayjs.extend(), là bước setup thêm mà người quen Moment.js có thể không lường trước.
- △README không nêu rõ ma trận trình duyệt hỗ trợ — chỉ nói 'all browsers supported' chung chung, nên đội nào nhắm tới trình duyệt cũ cần tự kiểm tra lại.
Day.js so với Moment.js và date-fns
Ai nên dùng Day.js
Đội đã quen API của Moment.js và muốn giữ nguyên tư duy đó trong một package nhẹ hơn là nhóm hợp với Day.js nhất. Nó cũng hợp với dự án mới quan tâm tới kích thước bundle mà không cần đủ mọi tính năng của Moment.js ngay từ đầu — bạn thêm plugin dần theo nhu cầu thay vì gánh hết mặc định. Dự án cần nhiều locale cùng lúc nên kiểm tra xem cách nạp từng locale qua dayjs.locale() có hợp với pipeline build của mình hay không trước khi chốt.
Câu hỏi thường gặp về Day.js
Day.js không phải drop-in đúng nghĩa — chính dự án mô tả mình 'largely' tương thích với Moment.js, không phải giống hệt. Phần lớn tên method và cách gọi nối tiếp giữ nguyên, nhưng Day.js bất biến còn Moment.js thì không, nên code nào dựa vào việc Moment.js đổi instance tại chỗ sẽ cần sửa lại khi migrate.
Day.js tự mô tả mình nặng 2kB, định vị rõ ràng là bản nhẹ hơn để thay Moment.js. README không đưa ra con số cụ thể của Moment.js để so sánh trực tiếp, nhưng con số 2kB chính là lý do chính khiến nhiều đội chọn Day.js thay vì Moment.js.
Day.js hỗ trợ thao tác bất biến ngay từ thiết kế — các method như .add() hay .startOf() trả về một instance Day.js mới thay vì sửa instance gốc. Đây là một trong những tính năng cốt lõi được nêu rõ, và cũng là khác biệt chính so với API mutable của Moment.js.
Timezone không nằm trong danh sách tính năng core của Day.js — danh sách đó gồm API kiểu Moment.js, bất biến, chainable, i18n, kích thước nhỏ và hỗ trợ trình duyệt. Day.js đưa các tính năng mở rộng vào qua plugin tự chọn (giống cách plugin advancedFormat hoạt động), nên timezone nhiều khả năng cũng cần thêm qua plugin chứ không có sẵn mặc định.
Day.js dùng giấy phép MIT, một giấy phép mã nguồn mở khá thoáng, cho phép dùng miễn phí trong dự án thương mại. README nêu rõ điều này, và MIT không bắt bạn phải mở mã nguồn dự án của mình hay trả phí để đưa Day.js vào sản phẩm thương mại.
Vấn đề mà Day.js giải quyết
Moment.js mutable — gọi .add() trên một instance là instance đó đổi luôn tại chỗ, dễ sinh bug khi instance ấy được share hoặc dùng lại ở nơi khác trong code. Vấn đề Day.js giải quyết khá hẹp và rõ: giữ nguyên tên method và tư duy của Moment.js để việc chuyển sang không phải học lại API, nhưng đổi mọi thao tác thành trả về instance mới và rút gọn cả thư viện xuống còn 2kB.
Repo liên quan
dayjs có đáng để bạn bỏ thời gian?
ChatGPT, Claude và Perplexity đều đọc được trang này. Hỏi thử xem họ nghĩ gì về dayjs.
