Moment.js项目状态

2020-09-15 14:09:03

Moment.js已经在数百万个项目中成功使用,我们很高兴为改善网络上的日期和时间做出了贡献。截至2020年9月,Moment.js每周的下载量超过1200万次!然而,Moment是为JavaScript生态系统的前一个时代而建立的,现在的Web看起来有很大的不同。Moment多年来有所发展,但它的设计基本上与2011年创建时的设计相同。考虑到有多少项目依赖于它,我们选择优先考虑稳定性而不是新功能。

例如,假设Moment对象是可变的。这是对Moment抱怨的一个常见来源。我们在我们的使用指南中解决了这一问题,但对于大多数新用户来说,它仍然令人惊讶。对于每个使用它的项目来说,将Moment更改为不变将是一个突破性的变化。创建一个不变的Moment v3&34;将是一项巨大的任务,将使Moment成为一个完全不同的库。既然其他库已经做到了这一点,我们认为保留可变的API更重要。

在现代应用程序中反对使用Moment的另一个常见论点是它的大小。Moment不能很好地使用现代的树抖动算法,因此它往往会增加Web应用程序捆绑包的大小。如果需要国际化或时区支持,Moment可能会变得非常大。现代Web浏览器(和Node.js)通过编码为ECMA-402的Intl对象公开国际化和时区支持。像LUXON(和其他库)这样的库利用了这一点,减少或消除了传输您自己的数据文件的需要。

最近,Chrome Dev工具开始显示仅针对大小更换Moment的建议。我们大体上支持这一举措。

团队已经详细讨论了这些问题。我们认识到许多现有的项目可能会继续使用Moment,但我们不鼓励在未来的新项目中使用Moment。

我们现在通常认为Moment是处于维护模式的遗留项目。它没有死,但它确实已经完成了。

我们可能会选择不修复错误或行为怪癖,特别是如果它们是长期存在的已知问题。

我们可以选择不接受对区域设置字符串或本地化日期格式的更正,特别是如果他们已经成功地论证了它们的当前形式。

你必须提出一个新的令人信服的论据来支持你的立场,并用重要的、非轶事的证据来证明你的观点。

如果您要求更改的字符串或格式反映在CLDR中,则必须先在那里提交更改并接受它。

在大多数情况下,你不应该为新项目选择时机。然而,有一些可能的原因您可能想要继续使用它。

Moment在Internet Explorer8及更高版本上运行良好。相比之下,Luxon仅适用于IE 10和更高版本,并且需要多边形填充才能执行此操作。您可以在卢克森的文档中阅读更多内容。

其他图书馆在Safari上也遇到了问题,特别是在移动设备上。如果您强烈要求支持较旧的浏览器,那么您可能希望使用Moment的时间更长一些。

但是,Day.js报告与IE8及更高版本兼容,因此您可能仍希望考虑该替代方案。

其他几个库,特别是日期选择器和图形库,将时刻作为依赖项。如果您正在使用这样的组件,但找不到替代组件,那么您已经在项目中包含了Moment。因此,在整个项目中继续使用Moment而不是包含另一个日期和时间库可能是有意义的。

如果您是Moment的老用户,您可能已经非常了解Moment的接口和限制了。如果是这样,并且上述问题对您来说都不是问题,那么您当然可以继续使用它。

编辑一些库仍然提供它们自己的区域设置和时区文件,如Moment和Moment-Timezone。

鲁克逊可以被认为是瞬间的进化。它是由艾萨克·坎布伦(Isaac Cambron)撰写的,他是“纪念碑”的长期撰稿人。请阅读卢克森为什么存在?以及Luxon文档中的For Moment Users页面。

Day.js被设计为Moment.js的最低限度替代,使用类似的API。它不是临时替代,但是如果您习惯使用Moment的API并且想要快速行动,可以考虑使用Day.js。

Date-FNS提供了一系列用于操作JavaScript Date对象的函数。有关更多详细信息,请滚动到Date-FNS主页上的“为什么选择Date-FNS?”。

JS-Joda是Java的Three-Ten Backport的JavaScript端口,它是Java SE 8 java.time包的JSR-310实现的基础。如果您熟悉java.time、Joda-Time或Noda Time,您会发现js-Joda具有可比性。

Date对象在内部表示一个精确到毫秒的Unix时间戳。它提供了在系统本地时区之间进行转换的函数,但它在内部始终是UTC。与Moment对象不同,它不能设置为使用其他时区;它没有模式的概念。

使用Date.parse或new date(<;string>;)在过去一直存在问题,并且实现不一致。当前规范定义了解析ISO 8601字符串的变体,其中仅日期形式(如";2020-09-14";)被解析为UTC,而不是按照ISO 8601解析为本地时间。即便如此,并不是所有的现代实现都正确地实现了这个规范(例如Safari)。其他类型的字符串也可以工作,但是解析它们是特定于实现的,可能会有很大的差异-尤其是对于较旧的浏览器。根据实现方式和字符串中提供的组件,您可能会对结果感到惊讶。出于这些原因,我们同意MDN的说法,即强烈不建议使用Date对象解析字符串。

现代JavaScript环境还将实现By ECMA-402规范,该规范提供Intl对象,并定义Date对象的toLocaleString、toLocaleDateString和toLocaleTimeString函数的行为选项。

并不是每个环境都会实现完整的规范。特别是,Node.js环境需要ICU提供的国际化支持。有关详细信息,请参阅Node.js文档。

ECMAScript Intl兼容性表(按kangax)可用于确定哪些功能受支持,哪些功能不受支持。

大多数较新的环境通过Intl.DateTimeFormat构造函数(以及Date.toLocaleString、Date.toLocaleDateString和Date.toLocaleTimeString)中的timezone选项提供IANA时区支持。此选项可用于获取Date对象的基于UTC的内部时间戳,并获取已转换为命名时区的字符串。但是,它不能用于将日期对象转换为不同的时区。

如果Date和Intl对象满足您的需要,并且您完全了解它们的限制,则可以考虑直接使用它们。

很快就有一天要编辑了,我们希望JavaScript中的日期和时间库不会有很大的需求。取而代之的是,我们将能够使用JavaScript语言本身的功能。虽然目前Date和Intl提供了一些功能,但我们从经验和数据中了解到,还有很大的改进空间。

通过ECMA TC39时间提案,正在努力用JavaScript语言制作更好的日期和时间API。

今天,您可以通过试验性的多层填充来尝试时间。请试一试,但不要将其用于生产(目前)!

也请考虑为这项工作做出贡献,特别是如果您有使用Moment或其他日期和时间库的经验。

所有代码应该都可以在这两个环境中运行,并且所有单元测试都可以在这两个环境中运行。

目前,ci系统使用以下浏览器:Windows XP上的Chrome,Windows 7上的IE 8、9和10,Windows 10上的IE 11,Linux上的最新Firefox,以及OSX 10.8和10.11上的最新Safari。

如果您想尝试下面的示例代码,只需打开浏览器的控制台并输入它们即可。

编辑注意:如果您要使用Moment时区的特定变体,例如,仅使用2012-2022年的数据,则需要将其从Builds目录导入,如下所示:

注意:在2.4.0中,全局导出的Moment对象被取消使用。它将在下一个主要版本中删除。

编辑如果您计划使用Moment with Require.js,我们强烈建议您阅读本文。还要升级到2.14.0或更高版本以获得最佳体验。

首先,您可能已经通过BOWER或NODE_MODULES或任何其他将oment.js和locales目录放在base文件夹中的方式获取了Moment。然后,您应该使用Adapt-pkg-main之类的工具,或者手动使用包配置。

Requijs.config({Packages:[{name:';Moment';,//此位置相对于baseUrl.。根据Moment的安装方式,选择BOWER_COMPOMENTS//或NODE_MODULES。地点:';[bower_components|node_modules]/moment';,Main:';Moment';}]});

使用上面的设置,您可以使用Moment和de localewith Moment/locale/de来要求内核。

//只需核心定义([';Moment';],Function(Moment){console.log(Moment().format(';LLLL';));//';2016年6月24日(星期五)1:42 AM';};//具有单一区域定义的核心([';Moment';,';Moment/Locale/de';],Function(Moment){Moment.locale(。Console.log(Moment().format(';llll';));//';freitag,24.Juni 2016 01:42';);//所有localesdefine([';moment/min/moment-with-locales';],函数(Moment){Moment.locale(';de';);console.log(Moment().format(';lll';));//';Freitag,24.JUNI 2016 01:42';});//检测到区域设置后,异步加载区域定义([';Required';,';Moment';],Function(Required,Moment){//在某个模块内。这是//在模块加载时间之前不知道区域设置的情况。Required([';Moment/Locale/de&39;],function(LocaleModule){//此处已加载区域设置,但尚未使用console.log(Moment().format(';LLLL';));//';2016年6月24日(星期五)1:42 AM';Moment.locale(';de';);//现在使用Moment,区域设置已正确设置。Console.log(Moment().format(';llll';));//';Freitag,24.Juni 2016 01:42';})});

Moment仍然会创建一个全局Moment,这对插件和其他第三方代码很有用。如果您希望挤压全局,请使用模块配置上noGlobal选项。

如果您不指定noGlobal,则全局导出的时刻将显示Printa弃用警告。从下一个主要版本开始,如果您想要这样的行为,您将不得不自己导出它。

对于2.5.x版,如果您使用其他依赖于Moment但不兼容AMD的插件,您可能需要将wrapShim:true添加到您的r.js配置中。

注意:为了能够将oment.js插件加载到requijs环境中,Moment被创建为命名模块。因此,Moment必须与";Moment";完全一样加载,并使用路径来确定目录。具有类似";供应商\Moment";路径的请求Moment将返回UNDEFINED。

注意:从2.9.0版开始,Moment会将自身导出为匿名模块,因此如果您只使用内核(没有区域设置/插件),那么如果您将其放在非标准位置,则不需要进行配置。

编者按:默认情况下,webpack捆绑了所有Moment.js locale(在Moment.js2.18.1中,缩写为160KB)。要去掉不必要的地区,只捆绑使用的地区,可以添加Moment-locales-webpack-plugin:

//webpack.config.jsconst MomentLocalesPlugin=require(';moment-locales-webpack-plugin';);module.exports={Plugin:[//剥离除“en”new MomentLocalesPlugin()以外的所有语言环境,//or:剥离除“en”、“es-us”和“ru”以外的所有语言环境//(“en”内置于Moment中,无法删除)new MomentLocalesPlugin({localesToKeep:[';es-us。],}),],};

为typecript 1.x编辑尝试在tsconfig.json文件的编译器选项中添加";allowSyntheticDefaultImports";:true,然后使用以下语法。

编辑以加载Moment,将其放在由baseURL配置中的System.config指定的路径中,然后将其导入到页面中。

如果需要将Moment加载为GLOBAL,可以使用元配置:

或者,要仅将力矩作为全局提供给特定依存关系,您可以执行以下操作:

编辑如果您在那里找不到要查找的内容,请尝试使用omomjs标签询问有关堆栈溢出的问题。

注意:在堆栈溢出上看到的一半以上的问题都可以通过这篇博客来回答。

您还可以使用GitHub问题跟踪器查找相关问题或打开新问题。

对于一般故障排除帮助,堆栈溢出是首选的论坛。Moment的维护人员非常积极地处理堆栈溢出,其他几个知识渊博的用户也是如此。最快的反应将在那里。

Moment.js为Date对象创建包装器,而不是修改本机Date.type。要获得此包装器对象,只需使用支持的输入类型之一调用Moment()即可。

Moment原型通过Moment.fn公开。如果您想要添加您自己的函数,您可以将它们放在那里。

为便于引用,Moment.Prototype上的任何方法在文档中都将被引用为Moment#Method。所以Moment.protocol type.format==oment.fn.format==Moment#format。

时刻(...)。是本地模式。不明确的输入(没有偏移量)假定为本地时间。明确的输入(带偏移量)调整为本地时间。

Oment.utc(...)。是UTC模式。不明确的输入假定为UTC。明确的输入调整为UTC。

ParseZone()保留传入的输入区域。如果输入不明确,则与本地模式相同。

请记住,时区和时区偏移是两码事。偏移量为-08:00并不一定意味着您处于美国太平洋时区。

编辑注意:从2.14.0版本开始,Moment([])和Moment({})现在也返回。在2.14.0之前,他们通常默认为今天开始,但这是武断的,所以它被更改了。

注意:函数参数未传入时默认为未定义。Moment将Moment(未定义)视为Moment()。

编辑从字符串创建时刻时,我们首先检查该字符串是否与已知的ISO 8601格式匹配,然后检查该字符串是否与RFC 2822日期时间格式匹配,如果未找到已知的格式,则在返回到新日期(字符串)的后备位置之前检查该字符串是否与已知的ISO 8601格式匹配。

警告:浏览器对解析字符串的支持不一致。因为没有关于应该支持哪些格式的规范,所以在某些浏览器中起作用的格式在其他浏览器中不起作用。

为获得一致的结果,解析除ISO 8601字符串以外的任何字符串,您应该使用字符串+格式。

2013-02-08#日历日期部分2013-02#月份日期部分2013-W06-5#星期日期部分2013-039#基本(短)日期部分20130208#基本(短)完整日期201303#基本(短)年+月2013#仅基本(短)年2013W065#基本(短)周,周#仅基本(短)周2013050#基本(短)序日(年+年日)。

时间部分也可以包括在内,与日期部分之间用空格或大写T隔开。

2013-02-08T09#用T2013-02-08 09#分隔的小时时间部分2013-02-08 09:30#用空格分隔的小时时间部分2013-02-08 09:30:26#小时、分钟和秒时间部分2013-02-08 09:30:26.123#小时、分钟、秒和毫秒时间部分2013-02-08 24:00:00.000#小时24,分钟,秒,毫秒等于第二天。以逗号20130208T080910.123#短日期和时间,最短为ms20130208T080910#短日期和时间,最短为秒20130208T0809#短日期和时间,最短为分钟20130208T08#短日期和时间,仅小时

2013-02-08 09#日历日期部分和小时时间部分2013-W06-5 09#周日期部分和小时时间部分2013-039 09#顺序日期部分和小时时间部分。

如果包含时间部分,也可以将UTC的偏移量包括为+-HH:MM、+-HHmm、+-HH或Z。

2013-02-08 09+07:00#+-hh:mm2013-02-08 09-0100#+-hhmm2013-02-08 09Z#Z2013-02-08 09:30:26.123+07:00#+-hh:mm2013-02-08 09:30:26.123+07#+-hh。

如果字符串与上述任何一种格式都不匹配,并且无法使用Date.parse进行解析,则Moment#isValid将返回False。

在解析RFC2822日期时间之前,清除字符串以删除任何注释和/或换行符。附加字符在格式中是合法的,但不会为创建有效的Moment实例添加任何内容。

清理后,字符串将在以下以空格分隔的部分中进行验证,全部使用英语:

2017年3月17日21:22 UT6 MAR 17 21:22:23 GMT 06 MAR 2017 21:22:23 ZMon 06 Mar 2017 21:22:23 ZMon,06 Mar 2017 21:22:23+0000。

月日(1位或2位),后跟三个字母的月份和2位或4位年份

由冒号(:)分隔的两位小时和分钟,后面可以选择另一个冒号和两位数的秒。

EST|CST|MST|PST|EDT|CDT|MDT|PDT:美国时区*。

编辑如果你知道输入字符串的格式,你可以用它来分析片刻。

默认情况下,解析器忽略非字母数字字符,因此以下两个代码将返回相同的内容。

在解析日期和时间时,您可能会得到意外的结果。下面的示例可能不会按照您的预期进行解析:

您可以使用严格模式,该模式将识别解析错误并将Moment对象设置为无效:

4位或2位数字年份。注意:在严格模式下只能解析4位数字。

版本2.10.5的YYYY支持2位年份,并将它们转换为接近2000的年份(与YY相同)。

在2.11.1中增加了Y。它将匹配任何数字,有符号的或无符号的。它对于不是4位数或在普通时代之前的年份很有用。它可以使用任何一年。

对于这些,小写标记使用区域设置感知的周开始天数,而大写标记使用ISO周日期开始天数。

也可以使用LT LTS L LL LLL LLLL使用区域设置感知的日期和时间格式。它们是在版本2.2.1中添加的,但LTS是在版本2.8.4中添加的。

从版本2.10.5开始:长度为4到9的小数第二令牌可以解析任意数量的数字,但只考虑前3位(毫秒)。如果您的时间打印有许多小数位,并且想要使用输入,请使用。

请注意,提供的S字符数仅在严格模式下解析时才相关。在标准模式下,S、SS、SSS、SSSS全部相等,并被解释为秒的分数。例如,.12始终为120毫秒,传递SS不会导致它被解释为12毫秒。

除非指定时区偏移量,否则解析字符串将在当前时区中创建日期。

时刻(";2010-10-20 4:30";,";YYYY-MM-DD HH:MM";);//解析为当地时间4:30(";2010-10-20 4:30+0000";,";YYYY-MM-DD HH:MM Z";);//解析为4:30 UTC。

如果解析的输入所产生的时刻不存在,则Moment#isValid将返回false。

时刻(";2010 13";,";YYYY MM";).isValid();//false(不是实月)时刻(";2010 11 31";,";YYYY MM DD&34;).isValid();//false(不是实日)时刻(";2010 2 29";,";YYYY MM DD&34;).isValid。2010 notamonth 29";,";YYYY MMM DD";).isValid();//false(非真实月份名称)。

从2.0.0版开始,区域设置键可以作为第三个参数传递给Moment()和Moment.utc()。

从2.3.0版开始,您可以为最后一个参数指定一个布尔值,以使Moment使用严格的解析。严格的解析要求格式和in。

.