要点:JavaScript日期格式化方案总结、最新消息(QQ/weChat)日期排序算法
一、Date类型
在讲述常见日期问题之前,先梳理一下Date类型的方法。
ECMAScript中的Date类型使用自UTC(Coordinated in Universal Time,国际协调时间)**1970年1月1日午夜(零时)**开始经过的毫秒数 来保存日期。
1.1 常用方法列表
方法
描述
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 对象的原始值。
1.2 时间日期格式参数
(1)年月日
Input
Example
Description
YYYY
2014
4 or 2 digit year
YY
14
2 digit year
Y
-25
Year with any number of digits and sign
Q
1..4
Quarter of year. Sets month to first month in quarter.
M MM
1..12
Month number
MMM MMMM
Jan..December
Month name in locale set by moment.locale()
D DD
1..31
Day of month
Do
1st..31st
Day of month with ordinal
DDD DDDD
1..365
Day of year
X
1410715640.579
Unix timestamp
x
1410715640579
Unix ms timestamp
(2)时分秒
Input
Example
Description
H HH
0..23
24 hour time
h hh
1..12
12 hour time used with a A
.
a A
am pm
Post or ante meridiem (Note the one character a p
are also considered valid)
m mm
0..59
Minutes
s ss
0..59
Seconds
S SS SSS
0..999
Fractional seconds
Z ZZ
+12:00
Offset from UTC as +-HH:mm
, +-HHmm
, or Z
1.3 补充
TimeZone&UTC Offsets:时区与偏移
人们经常会把时区与UTC偏移量搞混,UTC偏移量代表了某个具体的时间值与UTC时间之间的差异,通常用HH:mm形式表述。而TimeZone则表示某个地理区域,某个TimeZone中往往会包含多个偏移量,而多个时区可能在一年的某些时间有相同的偏移量。譬如America/Chicago, America/Denver, 以及 America/Belize在一年中不同的时间都会包含 -06:00 这个偏移。
1、格林威治时间
格林威治时间是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。
1 new Date ().getTimezoneOffset() / 60 ;
2、可以通过getUTCMonth
、setUTCMonth
等方法设置世界时的年、月、日、时、分、秒、毫秒。
3、把Date对象转化为字符串
1 2 3 new Date ().toString(); new Date ().toDateString() new Date ().toTimeString()
4、获取指定时间毫秒
1 2 3 4 Date .parse('08/14/2021' ); new Date ('08/14/2021' ).getTime(); Date .UTC(2021 , 8 , 14 );
UTC()方法中,月份从0开始且获得的毫秒值是世界时(即需要+8小时)
5、需要注意合理处理跨月、跨年的问题。
1 2 new Date (2016 , 7 , 32 ); new Date (2016 , 12 , 1 );
二、应用
2.1 获取过去第n天的时间
1 2 3 4 5 6 7 8 9 10 11 12 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" ); }
1 2 3 4 5 6 7 8 9 10 11 12 function setTimezone (tzn ) { tzn = tzn * 60 * -1 ; this .setTime(this .getTime() - (tzn - this .getTimezoneOffset()) * 60 * 1000 ); return this ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 function format (format ) { var o = { "M+" : this .getMonth() + 1 , "d+" : this .getDate(), "h+" : this .getHours(), "m+" : this .getMinutes(), "s+" : this .getSeconds(), "q+" : Math .floor((this .getMonth() + 3 ) / 3 ), "S" : this .getMilliseconds() }; 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; }
2.2 获取指定月份的天数
方式一:日历字典表
1 2 3 4 5 6 7 8 9 function getDaysInMonth (year, month ) { return [31 , (isLeapYear(year) ? 29 : 28 ), 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ][month]; }
1 2 3 4 5 6 function isLeapYear (year ) { return ((year % 4 === 0 && year % 100 !== 0 ) || year % 400 === 0 ); }
方式二:通过日历构造器
1 2 3 4 5 6 7 8 9 10 11 12 function getDaysInMonth (year, month ) { var date = new Date (year, month + 1 , 0 ); return date.getDate(); }
2.3 获取上个周的开始时间(上周一)&结束时间(上周日)
获取本周第一天,然后before(1)、before(7)
1 2 3 4 5 6 7 8 9 10 function getDayOfLastWeek ( ) { var weekday = new Date ().getDay(); weekday = weekday === 0 ? 7 : weekday; var firstDay = getBeforeDay(weekday + 7 -1 ); var lastDay = getBeforeDay(weekday); return { lastWeekFirstDay: firstDay, lastWeekLastDay: lastDay }; }
2.4 获取上个月的开始时间和结束时间
1 2 3 4 5 6 7 8 9 10 11 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" ) } }
2.5 将2021-8-4转换成2021-08-04格式
1 2 var strDate = '2005-8-5' ; strDate.replace(/\b(\w)\b/g , '0$1' )
2.6 间隔天数
1 2 var IntervalDays = (new Date ('2021/8/14' )-new Date ('2020/8/14' ))/1000 /60 /60 /24 +"天" console .log(IntervalDays)
2.7 间隔时间
1 2 3 4 5 6 7 var date1=new Date ("2021/08/14 10:00:00" ); var date2=new Date ("2021/08/13 10:00:01" ); var date3=date1-date2; var h=Math .floor(date3/3600000 ); var m=Math .floor((date3-h*3600000 )/60000 ); var s=(date3-h*3600000 -m*60000 )/1000 ; console .log("相差" +h+"小时" +m+"分" +s+"秒" )
2.8 当天日期
1 2 d = new Date (); var today = d.getFullYear()+"年" +(d.getMonth()+1 )+"月" +d.getDate()+"日" ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function detialTime (d ) { let old = new Date (d) let now = new Date () let h = old.getHours() let m = old.getMinutes() let Y = old.getFullYear() let M = old.getMonth()+1 let D = old.getDate() if (M<10 ) M = '0' + M if (D<10 ) D='0' + D if (h<10 ) h='0' +h if (m<10 ) m='0' +m return Y+'-' +M+'-' +D+' ' +h+':' +m }
2.9 数字日期转汉字
1 2 3 4 5 6 7 8 9 10 11 12 Date .prototype.getRead = function ( ) { var values = new Array ("零" , "一" , "二" , "三" , "四" , "五" , "六" , "七" , "八" , "九" ); var returnValue, temp; returnValue = this .getYear()+"年" ; temp = (this .getMonth()+1 )+"月" +this .getDate()+"日" ; temp = temp.replace(/(\d)(\d)/g ,"$1十$2" ).replace(/1十/g ,"十" ).replace(/十0/g ,"十" ); returnValue += temp; returnValue = returnValue.replace(/\d/g , function (sts ) {return values[parseInt (sts)]}); return returnValue; } var t=new Date (); document .write(t.getRead());
2.10 前N天或后N天的日期
方法一
1 2 3 4 5 6 7 8 9 10 11 function showdate (n ) { var uom = new Date (new Date ()-0 +n*86400000 ); uom = uom.getFullYear() + "-" + (uom.getMonth()+1 ) + "-" + uom.getDate(); return uom; } window .alert("今天是:" +showdate(0 )); window .alert("昨天是:" +showdate(-1 )); window .alert("明天是:" +showdate(1 )); window .alert("10天前是:" +showdate(-10 )); window .alert("5天后是:" +showdate(5 ));
方法二
1 2 3 4 5 6 7 8 9 10 11 12 function showdate (n ) { var uom = new Date (); uom.setDate(uom.getDate()+n); uom = uom.getFullYear() + "-" + (uom.getMonth()+1 ) + "-" + uom.getDate(); return uom; } window .alert("今天是:" +showdate(0 )); window .alert("昨天是:" +showdate(-1 )); window .alert("明天是:" +showdate(1 )); window .alert("10天前是:" +showdate(-10 )); window .alert("5天后是:" +showdate(5 ));
方法三
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Date .prototype.getDays=function ( ) { var _newDate=new Date (); _newDate.setMonth(_newDate.getMonth()+1 ); _newDate.setDate(0 ); $_days=_newDate.getDate(); delete _newDate; return $_days; } function showdate (n ) { var uom = new Date (); uom.setDate(uom.getDate()+n); uom = uom.getFullYear() + "-" + (uom.getMonth()+1 ) + "-" + uom.getDate()+"\n星期" +('天一二三四五六' .charAt(uom.getDay()))+"\n本月有" + uom.getDays()+"天" ; return uom; } window .alert("今天是:" +showdate(0 )); window .alert("昨天是:" +showdate(-1 )); window .alert("明天是:" +showdate(1 )); window .alert("10天前是:" +showdate(-10 )); window .alert("5天后是:" +showdate(5 ));
2.11 倒计时
1 2 3 4 5 6 7 8 9 10 11 setInterval (function ( ) { var nowTime = new Date (); var endTime = new Date ("2019-9-1 00:00:00" ); var seconds = parseInt ((endTime.getTime() - nowTime.getTime()) / 1000 ); var d = parseInt (seconds / 3600 / 24 ); var h = parseInt (seconds / 3600 % 24 ); var m = parseInt (seconds / 60 % 60 ); var s = parseInt (seconds % 60 ); document .getElementById("djs" ).innerHTML = "距离开学还有" + d +"天" + h + "小时" + m + "分钟" + s + "秒" ; }, 1000 );
1 2 3 4 5 6 7 8 9 var curTime = new Date ();var endTime = new Date ('2015,6,6' );var days = Math .ceil((endTime.getTime()-curTime.getTime())/(1000 *60 *60 *24 ));console .log("距高考只剩:" +days+"天" )
2.12 日期排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 const arrayList = [ { id: '1' , name: '2020年活动事件' , startData: '2020-07-01' , }, { id: '2' , name: '2019年活动事件' , startData: '2019-08-01' , }, { id: '3' , name: '2021活动事件' , startData: '2021-07-01' , }, { id: '4' , name: '2022活动事件' , startData: '2022-06-08' , } ] const timeData = arrayList.sort(function (a, b ) { return a.startData > b.startData ? 1 : -1 }) const timeData = arrayList.sort(function (a, b ) { return a.startData < b.startData ? 1 : -1 })
2.13 QQ首页消息日期处理
效果:
假设当天为2021/8/14
消息更新日期
显示格式
当天消息
11:30
昨天消息
昨天12:30
大于两天的消息
2021/8/12
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 dataTime (d ) { let old = new Date (d) let now = new Date () let h = old.getHours() let m = old.getMinutes() let Y = old.getFullYear() let M = old.getMonth()+1 let D = old.getDate() let nd = now.getTime() let nh = now.getHours() let n = now.getMinutes() let nY = now.getFullYear() let nM = now.getMonth()+1 let nD = now.getDate() if (D===nD && M===nM && Y===nY) { if (h<10 ) h='0' +h if (m<10 ) m='0' +m return h+':' +m } if (D+1 ===nD && M===nM && Y===nY) { if (h<10 ) h='0' +h if (m<10 ) m='0' +m return '昨天 ' +h+':' +m } else { return Y+'/' +M+'/' +D } },
测试:
1 2 3 console .log("今天是:" +showdate(0 ),"消息更新日期:" +dataTime(showdate(0 ))) console .log("昨天是:" +showdate(-1 ),"消息更新日期:" +dataTime(showdate(-1 ))) console .log("前天是:" +showdate(-2 ),"消息更新日期:" +dataTime(showdate(-2 )))
[showdate()](#2.10 前N天或后N天的日期)为获取前N天或后N天日期。
2.14 根据文件创建日期为文件命名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 fileName (e ) { let old = new Date (e) let Y = old.getFullYear() let M = old.getMonth()+1 let D = old.getDate() if (M<10 ) M = '0' + M if (D<10 ) D='0' + D return Y+M+D },
Tips:
Please indicate the source and original author when reprinting or quoting this article.