918,特殊的日子,希望一切安好。深圳最近奇怪的天气让人折腾,一会暴晒,一会下暴雨。请假在家休息,本来想睡个懒觉,但是一大早被电钻声吵醒,好吧,起床写点东西吧。今天跟大家分享下一款轻量级JavaScript日期库:date-fns。
在JavaScript中使用日期是一种痛苦。本地日期方法通常很冗长,有时也不一致 ---这也使它们易于出错。但是,好消息就在眼前。有几个库可以消除过时的痛苦。这些库是JavaScript日期,而jQuery是本机DOM API。
让我举一个例子。这是对堆栈溢出问题的公认答案,该问题询问如何获取每月的最后一天:
var t = new Date();alert( new Date(t.getFullYear(),
t.getMonth() + 1, 0, 23, 59, 59) );
当然可以,但是后面的数字getMonth
代表什么还不是很明显。现在,与更具可读性的对比一下:
const today = new Date();
console.log( lastDayOfMonth(today) );
该lastDayOfMonth
方法是date-fns提供的,date-fns是一个自称的综合工具集,用于在浏览器和Node.js中操纵JavaScript日期。
在本文中,我将向您展示如何启动和运行date-fns。阅读后,您将可以将其放入项目中,并利用其许多辅助方法轻松地操作日期。这将使代码t.getMonth() + 1, 0, 23, 59, 59
成为过去。
那么,为什么不仅仅使用Moment.js?
Moment.js是一个出色的库,用于在JavaScript中处理日期-它具有许多出色的功能,并提供了大量有用的实用程序。但是,并非没有批评者。
许多人都引用Moment对象是可变的(例如add
,诸如或subtract
更改原始Moment对象的操作)的事实,这使开发人员感到困惑,并且导致了bug。
它的大尺寸也受到了抨击。Moment在现代的"摇树"算法中不能很好地发挥作用,如果您需要国际化或时区支持,则可以使用相当大的JavaScript包快速找到自己。
到目前为止,Chrome的开发工具突显了以下事实:使用Moment可能会导致性能下降。
所有这些都导致Moment维护人员将项目置于维护模式,并阻止Moment在以后的新项目中使用。
我们认识到许多现有项目可能会继续使用Moment,但是我们想阻止Moment在以后的新项目中使用。相反,我们想推荐当今在现代应用中使用的绝佳选择。
这使date-fns成为Moment.js的最佳替代产品之一。
安装
从库的第二版开始,安装date-fns的唯一方法是作为npm软件包。
npm install date-fns
或通过纱线:
yarn add date-fns
您可以将date-fns与CommonJS模块系统以及ES模块一起使用:
// CommonJSconst
{ lastDayOfMonth } = require('date-fns');
要么:
// ES Modules
import { lastDayOfMonth } from 'date-fns';
不幸的是,当前没有可用的date-fns CDN版本。在本GitHub问题中讨论了将其删除和恢复的可能性。但是,这并不是说您不能在浏览器中使用它,只是需要在工作流程中引入捆绑步骤。
让我们看看现在如何做。
如何捆绑date-fns在浏览器中使用
我假设您在计算机上安装了Node和npm。如果没有,请查阅我们有关安装Node的教程。
接下来,安装Parcel。这是一个捆绑程序(类似于Webpack),它将允许您捆绑JavaScript并将其提供给浏览器。
npm install -g parcel-bundler
接下来,使用package.json
文件创建一个新项目。
mkdir date-fns
cd date-fns
npm init -y
如上所述安装date-fns库:
npm install date-fns
现在创建两个文件,index.html
和index.js
。
<!DOCTYPE html><html lang="en">
<head>
<meta charset="UTF-8" />
<title>date-fns</title>
</head>
<body>
<script src="index.js"></script>
</body></html>
import { lastDayOfMonth } from 'date-fns';
const today = new Date();
console.log(lastDayOfMonth(today));
启动包裹的内置开发服务器:
parcel index.html
并导航到http:// localhost:1234。您不会在页面上看到任何显示,但是如果您打开浏览器的控制台。您应该已经记录了当月的最后一天。
关于部署,您可以运行:
parcel build index.js --experimental-scope-hoisting
使Parcel在dist
文件夹中输出缩小且摇晃的捆绑包。
Date-fns基本用法
现在我们已经启动并运行,让我们看看date-fns可以做什么。
处理日期时最常见的任务之一是能够很好地格式化日期。我们可以使用date-fns 格式函数来做到这一点。
更改上面示例页面中的HTML,使其如下所示:
<body>
<h1>The date today is <span></span></h1>
<script src="index.js"></script></body>
在index.js
我们要导入的format
函数中,我们可以传递今天的日期和格式字符串。然后,我们想将结果输出到页面。
import { format } from 'date-fns';
const today = new Date();
const formattedDate = format(today, 'dd.MM.yyyy');
document.querySelector('h1 > span').textContent = formattedDate;
当然,我们不限于一种dd.MM.yyyy
格式,让我们尝试不同的方法:
const formattedDate = format(today, 'PPPP');
这将格式化像这样的输出:Wednesday, September 16th, 2020
。您可以在docs中找到格式设置选项的完整列表。
变更地区
如果您拥有使用多种语言的网站,那么date-fns可使国际化日期和时间变得简单。让我们迎接德国客人:
<h1>Heute ist <span></span></h1>
在JavaScript文件中,我们可以导入德语语言环境并将其传递给format
函数:
import { format } from 'date-fns';
import { de } from 'date-fns/locale';
const today = new Date();
const formattedDate = format(today, 'PPPP', { locale: de });
document.querySelector('h1 > span').textContent = formattedDate;
这将输出的东西沿着线:Heute ist Mittwoch, 16. September 2020
。
要求并以语言环境作为选项似乎很复杂,但与Moment.js缺省情况下使用所有语言环境使构建膨胀的方式不同,date-fns强制开发人员在需要时手动要求语言环境。
您可以通过查看node_modules/date-fns/locale
项目中的文件夹来查看可用语言环境的列表。
不变性,纯正和简单
date-fns的卖点之一是其功能纯净,易于解释。这样可以使代码易于理解,并在出现问题时更易于调试。
让我使用Moment.js作为反示例进行演示。如前所述,Moment中的日期是可变的,这可能导致意外行为。
const moment = require('moment');
const now = new Date();
const mNow = moment(now);
mNow.add('day', 3);
console.log(mNow.toDate());
mNow.add(3, 'day');
console.log(mNow.toDate());
// 2020-09-19T10:08:36.999Z
// 2020-09-22T10:08:36.999Z
这里有几件事要注意。Moment的add
函数对其接受其参数的顺序并不挑剔(尽管第一个方法现在将引发弃用警告)。但更令人困惑的是,如果add
连续调用多次,将不会得到相同的结果,因为Moment对象是可变的:
mNow.add(3, 'day'); // add 3 days
mNow.add(3, 'day'); // adds 3 **more** days
现在,将其与date-fns进行比较,date-fns会将参数保持在一个顺序中,并且始终返回相同的结果,并Date
为每次调用返回一个新对象。
import { isValid, parse } from 'date-fns';
const validDate = parse('29.02.2020', 'dd.MM.yyyy', new Date());
const invalidDate = parse('30.02.2020', 'dd.MM.yyyy', new Date());
console.log(validDate);
// Sat Feb 29 2020 00:00:00 GMT+0100 (Central European Standard Time)
console.log(invalidDate);
// Invalid Date
console.log(isValid(validDate));
// true
console.log(isValid(invalidDate));
// false
可以轻松地将其提取到一个小助手方法中,该方法对于例如验证表单中的用户输入很有用。
时区
date-fns的一个缺点是它目前没有像Moment.js那样的任何时区帮助程序功能,而是返回了代码在其上运行的本地时区。
这个堆栈溢出的答案提供了一些本机Date
对象如何实际不存储"实时区域"数据的背景知识。在该线程中,您会注意到他们提到了一种在JavaScript中原生设置时区的方法。这不是一个全面的解决方案,但是它适用于仅需要输出转换(从UTC或本地时间到特定时区)的许多情况。
new Date().toLocaleString("en-US", {timeZone: "America/New_York"});
时区实际上是一个要解决的复杂问题,这就是为什么MomentJS有一个单独的库。有计划在date-fns中添加时区支持,但是在撰写本文时,这仍在进行中。
但是,npm上有一个可用的软件包(基于对date-fns的未合并提取请求),该软件包使用Intl API添加了对date-fns v2.0.0的时区支持。每周下载14万次,这似乎很受欢迎,但是在撰写本文时,它已经有几个月没有更新了。
就是说,这是您可能会使用的方式:
npm i date-fns-tz
import { format, utcToZonedTime } from 'date-fns-tz';
const today = new Date(); // Wed Sep 16 2020 13:25:16
const timeZone = 'Australia/Brisbane'; // Let's see what time it is Down Under
const timeInBrisbane = utcToZonedTime(today, timeZone);
console.log(`
Time in Munich: ${format(today, 'yyyy-MM-dd HH:mm:ss')}
Time in Brisbane: ${format(timeInBrisbane, 'yyyy-MM-dd HH:mm:ss')}
`);
// Time in Munich: 2020-09-16 13:26:48
// Time in Brisbane: 2020-09-16 21:26:48
结论
Date-fns是一个很棒的小程序库,它为您提供了很多帮助程序方法,可用于在JavaScript中使用日期和时间。目前正在积极开发中,并且Moment.js已进入维护模式,这使其成为Moment.js的理想替代品。