Node.js日期时间处理工具: calendar2

  1. 简述与安装使用
  2. Date对象增强
  3. 日期(时间)等值对比
  4. 日期(时间)的增减
  5. 查询当前日期起止范围
  6. 静态方法:通过起止范围获取日历数组

1. 简述与安装使用

请别问为什么是 2

详细文档:https://www.npmjs.com/package/calendar2

calendar2 主要用于增强对日期和时间数据的处理,它包含两个对象:

  • Calendar
  • CalendarTypes

Calendar 对象继承自 Date 对象,因此可以使用 Date 对象中的所有函数。
CalendarTypes 对象是一个日期时间单位的枚举,仅包含一些常量如:YEAR(年份)、QUARTER(季度)、MONTH(月份)、WEEK(星期)、WEEKOFMONTH(包含选取当月所有的周范围列表,仅在函数 toBothDate() 调用时有效)、DAY(日期)、HOURS(小时)、MINUTES(分钟)、SECONDS(秒钟)。

1.1 安装

npm install calendar2 --save

1.2 使用

// 引入工具
const {Calendar, CalendarTypes} = require('calendar2');

// 实例化处理对象
const cal1 = new Calendar(); // 当前时间
const cal2 = new Calendar(new Date('2019-08-09')); // 构造传入一个Date对象
const cal3 = new Calendar('2019-08-09'); // 构造传入一个日期字符串

2. Date对象增强

image

我们可以通过 Date 对象的一些函数获取到想要分割的日期或时间数据,比如 getFullYear() 可以获取 2021 这样的具体年份。在 calendar2 中我们增加了几个增强函数,来处理一些特殊的分割数据:

  • getQuarter()季度索引。获取当前日期所在本年的季度索引, 以 0 作为起始表示第一季度,以此类推。若解析错误则返回 null。
  • getDayOfQuarter()季度中的第几天。用于获取当前日期,是本季度中的第几天,返回一个 Number 格式的天数统计数字。
  • toDate()获取日期部分。获取当前日期中的日期部分,默认返回日期格式为 yyyy-MM-dd。
  • toTime()获取时间部分。获取当前日期中的时间部分,返回字符串格式为 HH: mm:ss。
  • toDatetime()获取日期+时间部分。获取当前日期中的完整日期和时间部分,返回字符串格式为 yyyy-MM-dd HH: mm:ss。
  • toFormat( format_str )格式化日期文本。用于返回自定义格式化的日期/时间文本,默认格式为 yyyy-MM-dd hh: mm:ss,具体可用格式化方案参考 https://www.npmjs.com/package/date-format

示例

const now = new Calendar(); // 2020-06-04 16:42:05
 
now.getFullYear();     // 年份: 2020
now.getDayOfYear();     // 本日是该年中的第几天: 156
now.getQuarter();   // 季度索引: 1
now.getDayOfQuarter();   // 本日是该季度中的第几天: 65
now.getMonth();       // 月索引: 5
now.getDate();         // 本日是该月中的第几天: 4
now.getHours();       // 小时: 16
now.getMinutes();   // 分钟: 42
now.getSeconds();   // 秒钟: 5
 
now.toDate();        // 日期文本: '2020-06-04'
now.toTime();        // 时间文本: '16:42:05'
now.toDatetime();// 日期+时间: '2020-06-04 16:42:05'

now.toFormat('yyyy年MM月dd日 hh:mm');  // 自定义格式化: '2020年06月04日 16:42'

3. 日期(时间)等值对比

image

3.1 对比日期 equalsDate(otherDate)

由于 object != object, 因此函数简化了日期对比方式。对比一个日期,如果一致则返回 true,反之返回 false仅对比日期部分
参数 : string | Date | Calendar
返回值 : boolean

示例

const cal = new Calendar('2020-01-01 12:12:12');
cal.equalsDate('2020-01-01 16:16:16');  // 返回: true
cal.equalsDate(new Date('2020-01-02 12:12:12'));        // 返回: false
cal.equalsDate(new Calendar('2020-01-01 20:20:20'));        // 返回: true

3.2 对比日期+时间 equalsDateTime(otherDateTime)

仅对比日期+时间部分
参数 : string | Date | Calendar
返回值 : boolean

示例

const cal = new Calendar('2020-01-01 12:12:12');
cal.equalsDateTime('2020-01-01 16:16:16');  // 返回: false
cal.equalsDateTime(new Date('2020-01-02 12:12:12'));        // 返回: false
cal.equalsDateTime(new Calendar('2020-01-01 12:12:12'));        // 返回: true

4. 日期(时间)的增减 add(value, types)

image

在当前日期值基础上进行 ± 运算。函数并不会返回一个新值,而是对原有 Calendar 对象进行日期变更。
参数 : string | Date | Calendar
返回值 : boolean

示例

const cal = new Calendar('2020-05-20 18:01:01');

// 以下代码结果是以单独执行为例, 因为 add 函数会变更 cal 对象的当前日期值, 
// 因此同时执行的话不太容易与实例化中的日期时间进行参照对比
cal.add(1, CalendarTypes.DAY); // 增加 1 天 :  2020-05-21 18:01:01
cal.add(3, CalendarTypes.WEEK); // 增加 3 周 :  2020-06-10 18:01:01
cal.add(-6, CalendarTypes.MONTH); // 减少 6 月 :  2019-11-20 18:01:01
cal.add(+11, CalendarTypes.HOURS); // 增加 11 小时 :  2020-05-21 05:01:01

5. 查询当前日期起止范围

image

函数:toBothDate(types [, option])
查询 当前日期 所处范围的 开始日期 和 结束日期
参数 :

  • types [CalendarTypes] 筛选范围,可选枚举有:YEAR、QUARTER、MONTH、WEEK、WEEKOFMONTH。
  • option.first_weekday: 配置当前周首个的第一天是星期几,默认为 0 代表星期天,可选值范围:[0 ~ 6];
  • option.format_str: 配置当前日期范围返回的文本格式,默认为 yyyy-MM-dd;
  • 返回值 : object

示例

const cal = new Calendar('2020-05-20');

/**
 * 获取当前日期所在年份的 起止日期
 * 返回值: {
 *     today: '2020-05-20',
 *     dayOfYear: 141,
 *     beginDay: { year: 2020, month: 0, day: 1, text: '2020-1-1' }, 
 *     endDay: { year: 2020, month: 11, day: 31, text: '2020-12-31' }
 * }
 */
cal.toBothDate(CalendarTypes.YEAR);
 
 
/**
 * 获取当前日期所在季度的 起止日期
 * 返回值: {
 *     today: '2020年05月20日',
 *     dayOfQuarter: 50,
 *     beginDay: { year: 2020, month: 3, day: 1, text: '2020年04月01日' }, 
 *     endDay: { year: 2020, month: 5, day: 30, text: '2020年06月30日' }  
 * }
 */
cal.toBothDate(CalendarTypes.QUARTER, {format_str: 'yyyy年MM月dd日'});
 
 
/**
 * 获取当前日期所在月份的 起止日期
 * 返回值: {
 *     today: '2020-05-20 00:00',
 *     dayOfMonth: 20,
 *     beginDay: { year: 2020, month: 4, day: 1, text: '2020-05-01 00:00' }, 
 *     endDay: { year: 2020, month: 4, day: 31, text: '2020-05-31 23:59' } 
 * }
 */
cal.toBothDate(CalendarTypes.MONTH, {format_str: 'yyyy-MM-dd hh:mm'});
 
 
/**
 * 获取当前日期所在 周 的 起止日期
 * 周首日默认从 0 (星期天) 开始计算
 * 返回值: {
 *     today: '2020年05月20日',
 *     todayIndex: 3, // 表示当前周的第几天, 索引从 0 开始计算
 *     beginDay: { year: 2020, month: 4, day: 17, text: '2020年05月17日' }, 
 *     endDay: { year: 2020, month: 4, day: 23, text: '2020年05月23日' }
 * }
 */
cal.toBothDate(CalendarTypes.WEEK, {format_str: 'yyyy年MM月dd日'});
 
/**
 * 获取当前日期所在 周 的 起止日期
 * 周首日默认从 1 (星期一) 开始计算
 * 返回值: {
 *     today: '2020年05月20日',
 *     todayIndex: 2,
 *     beginDay: { year: 2020, month: 4, day: 18, text: '2020年05月18日' },
 *     endDay: { year: 2020, month: 4, day: 24, text: '2020年05月24日' }
 * }
 */
cal.toBothDate(CalendarTypes.WEEK, {first_weekday: 1, format_str: 'yyyy年MM月dd日'});
 
 
/**
 * 获取当前日期所在 周 的 起止日期, 包含当前月所包含的所有周列表
 * 周日期的计算是从 星期日 作为第一天, 进行计数
 * 返回值: {
 *     beginDay: { year: 2020, month: 4, day: 17, text: '2020-5-17' }, 
 *     endDay: { year: 2020, month: 4, day: 23, text: '2020-5-23' },
 *     today: '2020-05-20',
 *     todayIndex: 3,               // 当前日期所在weeks中的索引位置, 若无则值为 -1
 *     weeks: [ {
 *         begin: '2020-04-26',     // 完整的开始日期
 *         end: '2020-05-02',       // 完整的结束日期
 *         begin_format: '2020-04-26', // 日期格式化之后的开始时间文本
 *         end_format: '2020-05-02', // 日期格式化之后的结束时间文本
 *         isCurrentWeek: false,    // 是否是当前日期所在的周
 *         raw: '4/26  ~  5/2',     // (待废弃, 勿用)
 *         title: '4/26  ~  5/2',   // 简单字符串表示
 *         beginDate: 26,           // 开始日期的日份
 *         endDate: 2               // 结束日期的日份
 *         beginOfMonth: '4/26',    // 包含月/日的开始日期
 *         endOfMonth: '5/2',       // 包含月/日的结束日期
 *       },
 *       ...
 *       {
 *         begin: '2020-05-31',
 *         end: '2020-06-06',
 *         begin_format: '2020-05-31', // 日期格式化之后的开始时间文本
 *         end_format: '2020-06-06', // 日期格式化之后的结束时间文本
 *         isCurrentWeek: false,
 *         raw: '5/31  ~  6/6',
 *         title: '5/31  ~  6/6',
 *         beginDate: 31,
 *         endDate: 6,
 *         beginOfMonth: '5/31',
 *         endOfMonth: '6/6',
 *       }
 *     ],
 * }
 */
cal.toBothDate(CalendarTypes.WEEKOFMONTH);

6. 静态方法:通过起止范围获取日历数组

image

一些时候,我们希望给定一个时间范围,以此来获取这个时间范围中的所有单位(比如日期,或者月份)数组。此时可以使用静态方法 getDateUnits(option)

函数:Calendar.getDateUnits(option)
获取某范围内的所有日期单位, 范围确定方式有两种:

  1. 通过 beginend 确定日期范围。优先级靠前(参数都满足的情况下优先使用方案1范围)
  2. 通过 seed 作为当前的种子日期, 以 incr 作为种子增量, 范围为 seed ~ (seed + incr) 之间;

参数 :

  • option.begin [String|Date] 起始日期
  • option.end [String|Date] 结束日期
  • option.incr [Integer] 日期增量
  • option.seed [String|Date] 种子日期
  • option.particle [CalendarTypes] 需要返回的日期单位数组粒度,仅支持:YEAR、MONTH、DAY,默认为: CalendarTypes.DAY (返回的数据会包含范围内的每一天)
  • option.format [String] 返回数据格式化方式,默认为 yyyy-MM-dd
  • option.order [String] 排序方式, 支持方式: ASC(正序)、DESC(倒序), 默认为 ASC
  • 返回值 : {begin_date, end_date, dates}

示例1: 通过 begin 和 end 获取日期范围

// 1-1 日范围筛选
Calendar.getDateUnits({
    begin: '2020-06-29',
    end: '2020-07-4',
});
 
/**
 * 1-1 返回值: 
 * {
 *   begin_date: '2020-06-29',
 *   end_date: '2020-07-04',
 *   dates: [
 *     { year: 2020, month: 5, day: 29, txt: '2020-06-29' },
 *     { year: 2020, month: 5, day: 30, txt: '2020-06-30' },
 *     { year: 2020, month: 6, day: 1, txt: '2020-07-01' },
 *     { year: 2020, month: 6, day: 2, txt: '2020-07-02' },
 *     { year: 2020, month: 6, day: 3, txt: '2020-07-03' },
 *     { year: 2020, month: 6, day: 4, txt: '2020-07-04' }
 *   ]
 * }
 */
 
 
 
// 1-2 月范围筛选
Calendar.getDateUnits({
    begin: '2020-11', // 范围可以只到月份
    end: '2021-02-21', // 也可以是具体的日期字符串或 Date 对象
    particle: CalendarTypes.MONTH,
});
 
/**
 * 1-2 返回值: 
 * {
 *   begin_date: '2020-11',
 *   end_date: '2021-02',
 *   dates: [
 *     { year: 2020, month: 10, txt: '2020-11' },
 *     { year: 2020, month: 11, txt: '2020-12' },
 *     { year: 2021, month: 0, txt: '2021-01' },
 *     { year: 2021, month: 1, txt: '2021-02' }
 *   ]
 * }
 */
 
 
 
// 1-3 日范围筛选
Calendar.getDateUnits({
    begin: '2019-06-29',
    end: '2025',
    particle: CalendarTypes.YEAR,
    order: 'DESC', // 倒序排序
    format: 'yyyy年', // 格式化
});
 
/**
 * 1-3 返回值: 
 * {
 *   begin_date: '2019年',
 *   end_date: '2025年',
 *   dates: [
 *     { year: 2025, txt: '2025年' },
 *     { year: 2024, txt: '2024年' },
 *     { year: 2023, txt: '2023年' },
 *     { year: 2022, txt: '2022年' },
 *     { year: 2021, txt: '2021年' },
 *     { year: 2020, txt: '2020年' },
 *     { year: 2019, txt: '2019年' }
 *   ]
 * }
 */

示例2: 通过 seed 作为当前的种子日期, 以 incr 作为种子增量获取范围:

// 2-1 日期向前增加 5 天 (返回包含 seed 日期的 6 条数据)
Calendar.getDateUnits({
    seed: '2020-06-29',
    incr: 5,
});
 
/**
 * 2-1 返回值: 
 * {
 *   begin_date: '2020-06-29',
 *   end_date: '2020-07-04',
 *   dates: [
 *     { year: 2020, month: 5, day: 29, txt: '2020-06-29' },
 *     { year: 2020, month: 5, day: 30, txt: '2020-06-30' },
 *     { year: 2020, month: 6, day: 1, txt: '2020-07-01' },
 *     { year: 2020, month: 6, day: 2, txt: '2020-07-02' },
 *     { year: 2020, month: 6, day: 3, txt: '2020-07-03' },
 *     { year: 2020, month: 6, day: 4, txt: '2020-07-04' }
 *   ]
 * }
 */
 
 
 
// 2-2 日期向后减少 5 天 (返回包含 seed 日期的 6 条数据)
Calendar.getDateUnits({
    seed: '2020-06-2',
    incr: -5, // 增量给与负数
});
 
/**
 * 2-2 返回值: 
 * {
 *   begin_date: '2020-05-28',
 *   end_date: '2020-06-02',
 *   dates: [
 *     { year: 2020, month: 4, day: 28, txt: '2020-05-28' },
 *     { year: 2020, month: 4, day: 29, txt: '2020-05-29' },
 *     { year: 2020, month: 4, day: 30, txt: '2020-05-30' },
 *     { year: 2020, month: 4, day: 31, txt: '2020-05-31' },
 *     { year: 2020, month: 5, day: 1, txt: '2020-06-01' },
 *     { year: 2020, month: 5, day: 2, txt: '2020-06-02' }
 *   ]
 * }
 */

谢谢观赏,如有问题,或希望改进的地方请在评论区告知我哦。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容