npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

eslint-plugin-date-consistency

v1.0.4

Published

ESLint plugin to prevent mixing native Date with date libraries

Readme

eslint-plugin-date-consistency

Language / 언어 / 语言 / 言語: English | 한국어 | 简体中文 | 日本語

npm version license

一个强制日期处理一致性的 ESLint 插件 — 防止在已使用日期库的项目中意外使用原生 Date 对象,并标记已废弃的库(如 Moment.js)。

为什么需要它?

当项目引入了 dayjsdate-fns 这样的日期库后,开发者仍可能出于习惯使用 new Date()。这会带来两个问题:

  1. 不一致性 — 代码库混用两种日期表示方式,使行为难以推断。
  2. 重新引入 Bug — 原生 Date 对象有许多众所周知的陷阱(从 0 开始的月份索引、可变性、夏令时边界情况、时区问题),而库正是为了解决这些问题而设计的。
// ❌ 不一致 — 混用 dayjs 和原生 Date
import dayjs from 'dayjs';
const d = new Date(); // 应该使用 dayjs()

// ✅ 一致
import dayjs from 'dayjs';
const d = dayjs();

该插件在 lint 阶段捕获这些问题,在代码审查或上线之前发现隐患。


规则列表

| 规则 | 描述 | 推荐 | |------|------|:----:| | no-new-date-with-lib | 在已导入日期库的文件中标记 new Date() 的使用 | ✅ | | no-deprecated-date-lib | 标记已废弃库的导入(如 Moment.js) | ✅ |


环境要求

| 要求 | 最低版本 | |------|:--------:| | Node.js | >= 20.0.0 | | ESLint | >= 8.0.0 |

包管理器: 支持 npm、pnpm 和 yarn。

TypeScript: 非必需。同时支持 JavaScript 和 TypeScript 项目。


安装

# npm
npm install --save-dev eslint-plugin-date-consistency

# yarn
yarn add --dev eslint-plugin-date-consistency

# pnpm
pnpm add --save-dev eslint-plugin-date-consistency

对等依赖: eslint >= 8.0.0


配置

方式一 — 推荐配置(最简单)

使用合理的默认值启用所有推荐规则。

// eslint.config.js
import dateConsistency from 'eslint-plugin-date-consistency';

export default [dateConsistency.configs.recommended];

方式二 — 手动 Flat Config

// eslint.config.js
import dateConsistency from 'eslint-plugin-date-consistency';

export default [
  {
    plugins: {
      'date-consistency': dateConsistency,
    },
    rules: {
      'date-consistency/no-new-date-with-lib': 'warn',
      'date-consistency/no-deprecated-date-lib': 'warn',
    },
  },
];

方式三 — 传统配置(.eslintrc.js

module.exports = {
  plugins: ['date-consistency'],
  rules: {
    'date-consistency/no-new-date-with-lib': 'warn',
    'date-consistency/no-deprecated-date-lib': 'warn',
  },
};

规则详情

date-consistency/no-new-date-with-lib

在已导入配置中指定的日期库的文件中,禁止使用 new Date()(以及可选的 Date.now()Date.parse())。

错误信息包含检测到的库名称,以便您知道应该使用什么替代:

'dayjs' is already imported. Use it instead of 'new Date()'.

选项

'date-consistency/no-new-date-with-lib': ['warn', {
  libs: ['dayjs', 'date-fns', 'moment', 'luxon'], // 默认值
  allowAsArgument: false,                          // 默认值
  checkStaticMethods: false,                       // 默认值
  ignorePatterns: [],                              // 默认值
  banNativeDate: false,                            // 默认值
}]

| 选项 | 类型 | 默认值 | 描述 | |------|------|--------|------| | libs | string[] | ['dayjs', 'date-fns', 'moment', 'luxon'] | 要监视的日期库列表。支持子路径导入(如 date-fns/format)和 scoped 包。 | | allowAsArgument | boolean | false | 为 true 时,允许将 new Date() 作为函数调用的参数(如 dayjs(new Date()))。 | | checkStaticMethods | boolean | false | 为 true 时,同时检查 Date.now()Date.parse()Date.UTC()。 | | ignorePatterns | string[] | [] | 始终允许 new Date() 的文件 glob 模式。适用于测试文件。 | | banNativeDate | boolean | false | 为 true 时,即使文件中没有导入日期库,也禁止使用 new Date()。 |

会触发警告的情况

// ESM 默认导入
import dayjs from 'dayjs';
const d = new Date(); // ⚠ 'dayjs' is already imported. Use it instead of 'new Date()'.

// 命名导入
import { format } from 'date-fns';
const d = new Date(); // ⚠ 'date-fns' is already imported. Use it instead of 'new Date()'.

// 子路径导入
import { format } from 'date-fns/format';
const d = new Date(); // ⚠

// CommonJS require
const dayjs = require('dayjs');
const d = new Date(); // ⚠

// 带参数的 new Date()
import dayjs from 'dayjs';
const d = new Date('2024-01-01'); // ⚠

// 作为参数传递(allowAsArgument: false 为默认值)
import dayjs from 'dayjs';
const d = dayjs(new Date()); // ⚠

// checkStaticMethods: true 时的 Date.now()
import dayjs from 'dayjs';
const ts = Date.now(); // ⚠ 'dayjs' is already imported. Use it instead of 'Date.now'.

允许的情况

// 没有导入日期库 — 可以使用原生 Date
const d = new Date();

// 仅类型导入不会触发规则
import type { Dayjs } from 'dayjs';
const d = new Date(); // ok

// instanceof 是类型检查,不是构造函数调用
import dayjs from 'dayjs';
if (value instanceof Date) { /* ok */ }

// 默认允许 Date.now()(checkStaticMethods: false)
import dayjs from 'dayjs';
const ts = Date.now(); // ok

// allowAsArgument: true 时
import dayjs from 'dayjs';
const d = dayjs(new Date()); // allowAsArgument 为 true 时 ok

// 不在 libs 列表中的库
import axios from 'axios';
const d = new Date(); // ok

使用示例

严格模式 — 全局禁止 new Date()

'date-consistency/no-new-date-with-lib': ['error', {
  banNativeDate: true,
  checkStaticMethods: true,
  ignorePatterns: ['**/*.test.*', '**/*.spec.*', '**/__tests__/**'],
}]

在测试文件中允许 new Date()

'date-consistency/no-new-date-with-lib': ['warn', {
  ignorePatterns: ['**/*.test.*', '**/*.spec.*', '**/__tests__/**'],
}]

自定义库列表

'date-consistency/no-new-date-with-lib': ['error', {
  libs: ['dayjs', 'my-internal-date-utils'],
}]

允许 dayjs(new Date()) 作为迁移过渡

'date-consistency/no-new-date-with-lib': ['warn', {
  allowAsArgument: true,
}]

date-consistency/no-deprecated-date-lib

标记已废弃或不再维护的日期库的导入。默认针对 Moment.js,该库自 2020 年 9 月起进入维护模式(不再添加新功能,仅修复安全问题)。

'moment' is in maintenance mode. Consider migrating to dayjs or date-fns.

选项

'date-consistency/no-deprecated-date-lib': ['warn', {
  deprecated: ['moment'],                         // 默认值
  alternatives: { moment: 'dayjs or date-fns' }, // 默认值
}]

| 选项 | 类型 | 默认值 | 描述 | |------|------|--------|------| | deprecated | string[] | ['moment'] | 要标记的库列表。 | | alternatives | Record<string, string> | { moment: 'dayjs or date-fns' } | 每个废弃库的建议替代方案,显示在警告消息中。 |

会触发警告的情况

import moment from 'moment';
// ⚠ 'moment' is in maintenance mode. Consider migrating to dayjs or date-fns.

const moment = require('moment');
// ⚠ 相同警告

import moment from 'moment/moment'; // 子路径导入
// ⚠ 相同警告

允许的情况

// 仅类型导入不会触发警告
import type { Moment } from 'moment';

// 非废弃库
import dayjs from 'dayjs';
import { format } from 'date-fns';
import { DateTime } from 'luxon';

使用示例

自定义废弃列表和替代方案

'date-consistency/no-deprecated-date-lib': ['error', {
  deprecated: ['moment', 'fecha'],
  alternatives: {
    moment: 'dayjs',
    fecha: 'date-fns',
  },
}]

仅警告,不建议替代方案

'date-consistency/no-deprecated-date-lib': ['warn', {
  deprecated: ['my-old-date-lib'],
  alternatives: {}, // 不显示替代建议
}]

常用配置

dayjs 项目 — 推荐起始配置

import dateConsistency from 'eslint-plugin-date-consistency';

export default [
  {
    plugins: { 'date-consistency': dateConsistency },
    rules: {
      'date-consistency/no-new-date-with-lib': ['warn', {
        libs: ['dayjs'],
        ignorePatterns: ['**/*.test.*', '**/*.spec.*'],
      }],
      'date-consistency/no-deprecated-date-lib': 'warn',
    },
  },
];

date-fns 项目 — 严格模式

import dateConsistency from 'eslint-plugin-date-consistency';

export default [
  {
    plugins: { 'date-consistency': dateConsistency },
    rules: {
      'date-consistency/no-new-date-with-lib': ['error', {
        libs: ['date-fns'],
        checkStaticMethods: true,
        ignorePatterns: ['**/*.test.*'],
      }],
      'date-consistency/no-deprecated-date-lib': 'error',
    },
  },
];

从 Moment.js 迁移

同时使用两个规则,防止新增 Moment.js 使用的同时强制使用替代方案:

import dateConsistency from 'eslint-plugin-date-consistency';

export default [
  {
    plugins: { 'date-consistency': dateConsistency },
    rules: {
      'date-consistency/no-deprecated-date-lib': ['error', {
        deprecated: ['moment'],
        alternatives: { moment: 'dayjs' },
      }],
      'date-consistency/no-new-date-with-lib': ['warn', {
        libs: ['dayjs'],
      }],
    },
  },
];

已知限制

CJS require 必须出现在 new Date() 之前

ESLint 对 AST 节点进行从上到下的单次遍历。如果 require() 调用出现在同一文件中 new Date() 之后,规则将无法检测到它:

const d = new Date();          // ← 未被标记:require 尚未被处理
const dayjs = require('dayjs');

这是 ESLint 单次遍历访问者模型的固有限制。解决方法是将 require() 放在文件顶部 — 这本来就是标准做法。

ESM import 声明根据语言规范始终提升到文件顶部,因此此限制不适用于 ESM。

allowAsArgument 允许在任何函数调用中使用 new Date()

allowAsArgument: true 时,只要 new Date() 作为参数传递给任何函数,规则就会放行 — 不仅限于日期库函数:

import dayjs from 'dayjs';

dayjs(new Date());           // ✅ 允许 — 预期的使用场景
someOtherFn(new Date());     // ✅ 也允许 — 可能出乎意料

如果需要更严格的控制,保持 allowAsArgument: false(默认值),并在需要时为 dayjs(new Date()) 单独添加 lint 禁用注释。


更新日志

请参阅 CHANGELOG.md

贡献

请参阅 CONTRIBUTING.md

许可证

MIT