JavaScript日期处理

​ 日期处理,在前端开发过程中会经常遇到。不同的开发者处理日期都有自己的想法。下面提供几种常见的日期问题。

​ 当然,Github上提供了好多优秀的日期处理插件(如:Datejs、date-fns、jquery-dateFormat),然而当处理一些简单的日期操作去引用插件,还是挺耗费资源。

写在前面

  • 时区(Time Zone):是地球上的区域使用同一个时间定义;

  • 世界标准/协调时间(Coordinated Universal Time):1970年1月1日午夜(零时)开始经过的毫秒数来保存日期;

    new Date().getTime() // 任意时区下当前时间的毫秒值相同

  • 格林威治时间(GMT):是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。

    ·new Date().getTimezoneOffset() / 60; // -8,即英国的当地时间比中国的北京时间晚8小时

Date类型

在讲述常见日期问题之前,先梳理一下Date类型的方法。

常用方法列表:

方法 描述
Date() 返回当日的日期和时间。
getDate() 从 Date 对象返回一个月中的某一天 (1 ~ 31)。
getDay() 从 Date 对象返回一周中的某一天 (0 ~ 6)。
getMonth() 从 Date 对象返回月份 (0 ~ 11)。
getFullYear() 从 Date 对象以四位数字返回年份。
getHours() 返回 Date 对象的小时 (0 ~ 23)。
getMinutes() 返回 Date 对象的分钟 (0 ~ 59)。
getSeconds() 返回 Date 对象的秒数 (0 ~ 59)。
getMilliseconds() 返回 Date 对象的毫秒(0 ~ 999)。
getTime() 返回 1970 年 1 月 1 日至今的毫秒数。
getTimezoneOffset() 返回本地时间与格林威治标准时间 (GMT) 的分钟差。
parse() 返回1970年1月1日午夜到指定日期(字符串)的毫秒数。
setDate() 设置 Date 对象中月的某一天 (1 ~ 31)。
setMonth() 设置 Date 对象中月份 (0 ~ 11)。
setFullYear() 设置 Date 对象中的年份(四位数字)。
setHours() 设置 Date 对象中的小时 (0 ~ 23)。
setMinutes() 设置 Date 对象中的分钟 (0 ~ 59)。
setSeconds() 设置 Date 对象中的秒钟 (0 ~ 59)。
setMilliseconds() 设置 Date 对象中的毫秒 (0 ~ 999)。
setTime() 以毫秒设置 Date 对象。
toSource() 返回该对象的源代码。
toString() 把 Date 对象转换为字符串。
toTimeString() 把 Date 对象的时间部分转换为字符串。
toDateString() 把 Date 对象的日期部分转换为字符串。
toUTCString() 根据世界时,把 Date 对象转换为字符串。
toLocaleString() 根据本地时间格式,把 Date 对象转换为字符串。
toLocaleTimeString() 根据本地时间格式,把 Date 对象的时间部分转换为字符串。
toLocaleDateString() 根据本地时间格式,把 Date 对象的日期部分转换为字符串。
UTC() 根据世界时返回 1970 年 1 月 1 日 到指定日期的毫秒数。
valueOf() 返回 Date 对象的原始值。

补充:

  • 可以通过getUTCMonth、setUTCMonth等方法设置世界时的年、月、日、时、分、秒、毫秒。
  • 把Date对象转化为字符串
new Date().toString();      // "Fri Aug 05 2016 11:54:25 GMT+0800 (CST)"
   new Date().toDateString()   // "Fri Aug 05 2016"
   new Date().toTimeString()   // "11:54:48 GMT+0800 (CST)"
  • 获取指定时间毫秒
/* 2016年8月5日 */
Date.parse('08/05/2016'); // 1470326400000
new Date('08/05/2016').getTime(); // 1470326400000
Date.UTC(2016, 7, 5); // 1470355200000

UTC()方法中,月份从0开始且获得的毫秒值是世界时(即需要+8小时)

获取过去第n天的时间

/**
 * 获取过去的n天
 * @param data 过去的天数
 * @param date 指定日期
 */
function getBeforeDay(data, date) {
  var date = date || new Date(),
      timezone = "+08:00";  // 时区
  var now = setTimezone.call(date, timezone.replace(":",".")); // 获取指定时区的当前日期
  var beforeDay = new Date(Date.parse(now.toString()) - 86400000 * data);
  return format.call(beforeDay, "yyyy/MM/dd"); // 格式化日期
}
/**
 * 设置时区
 * @param tzn
 * @returns {setTimezone}
 */
function setTimezone(tzn) {
  tzn = tzn * 60 * -1;
  this.setTime(this.getTime() - (tzn - this.getTimezoneOffset()) * 60 * 1000);
  return this;
}
/**
 * 日期格式化
 * @param format
 * @returns {*}
 */
function format (format) {
  var o = {
    "M+": this.getMonth() + 1,   //month
    "d+": this.getDate(),      //day
    "h+": this.getHours(),     //hour
    "m+": this.getMinutes(),   //minute
    "s+": this.getSeconds(),   //second
    "q+": Math.floor((this.getMonth() + 3) / 3), //quarter
    "S": this.getMilliseconds() //millisecond
  };
  if (/(y+)/.test(format)) {
    format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
  }
  for (var k in o) {
    if (new RegExp("(" + k + ")").test(format)) {
      format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
    }
  }
  return format;
}

获取指定月份的天数

方式一:日历字典表

/**
 * 获取指定月份的天数
 * 像月份、星期这样可列举且不易发生改变、数据项不是很大的,建议使用字典直接展现出来!!
 * @param year 年份,如:2016
 * @param month 月份,如:0(注意,遵循默认日历,从0开始)
 */
function getDaysInMonth (year, month) {
  return [31, (isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
}

/**
 * 判断是否为瑞年
 */
function isLeapYear(year) { 
  return ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); 
}

方式二:通过日历构造器

/**
 * 获取指定月份的天数
 * @param year 年份,如:2016
 * @param month 月份,如:0(注意,遵循默认日历,从0开始)
 */
function getDaysInMonth (year, month) {
  // 将天置为0,会获取其上个月的最后一天
  // 获取1月份的天数
  // new Date(2016, 2 , 0) ==> Mon Feb 29 2016 00:00:00 GMT+0800 (CST)
  var date = new Date(year, month + 1, 0);
  return date.getDate();
}

获取上个周的开始时间(上周一)&结束时间(上周日)

获取本周第一天,然后before(1)、before(7)

function getDayOfLastWeek(){
  var weekday = new Date().getDay();    // 获取当前是周几(周日:0)
  weekday = weekday === 0 ? 7 : weekday;
  var firstDay = getBeforeDay(weekday + 7 -1);
  var lastDay = getBeforeDay(weekday);
  return {
    lastWeekFirstDay: firstDay,
    lastWeekLastDay: lastDay
  };
}

获取上个月的开始时间和结束时间

/**
 *  new Date(年, 月, 日)  ==> 月份从0开始
 */
function getDayOfLastMonth(){
  var date = new Date(),
      currentMonth = date.getMonth();
  return {
    lastMonthFirstDay: format.call(new Date(date.getFullYear(), currentMonth - 1, 1), "yyyy/MM/dd"),
    lastMonthLastDay: format.call(new Date(date.getFullYear(), currentMonth, 0), "yyyy/MM/dd")
  }
}

由上述示例,可获取当月的第一天和最后一天及指定月份的第一天和最后一天。

格外注意

需要注意合理处理跨月、跨年的问题。

new Date(2016, 7, 32);  // Thu Sep 01 2016 00:00:00 GMT+0800 (CST)
new Date(2016, 12, 1);  // Sun Jan 01 2017 00:00:00 GMT+0800 (CST)

最后,推荐两个不错的插件:
- 日历插件,非常灵活:bootstrap-daterangepicker
- 日期转换、格式化:moment

你可能感兴趣的:(JavaScript)