[TOC]
# date對象
## 構造
~~~
new Date() :返回當前的本地日期和時間
new Date(milliseconds) :把毫秒數轉換為 Date 對象
new Date(-1000 * 60 * 1); // 倒退1分鐘的毫秒數
~~~
~~~
new Date(dateStr) :把字符串轉換為 Date 對象
參數:
1) yyyy/MM/dd HH:mm:ss (推薦):若省略時間,返回的 Date 對象的時間為 00:00:00。
2) yyyy-MM-dd HH:mm:ss :若省略時間,返回的 Date 對象的時間為 08:00:00(加上本地時區)。若不省略時間,此字符串在IE中會轉換失敗!
3) new Date('August 19, 1975 23:15:30 GMT-02:00');
~~~
~~~
new Date(year, month, opt_day, opt_hours, opt_minutes, opt_seconds, opt_milliseconds) :把年月日、時分秒轉換為 Date 對象
參數
①year {int} :年份;4位數字。如:1999、2014
②month {int} :月份;2位數字。從0開始計算,0表示1月份、11表示12月份。
③opt_day {int} 可選:號; 2位數字;從1開始計算,1表示1號。
④opt_hours {int} 可選:時;2位數字;取值0~23。
⑤opt_minutes {int} 可選:分;2位數字;取值0~59。
⑥opt_seconds {int} 可選:秒;2未數字;取值0~59
⑦opt_milliseconds {int} 可選:毫秒;取值0~999
~~~
## 實例方法
Date 對象的實例方法主要分為2種形式:本地時間和 UTC 時間。同一個方法,一般都會有此2種時間格式操作(方法名帶 UTC 的,就是操作 UTC 時間),這里主要介紹對本地時間的操作。
### get方法
* getFullYear() :返回 Date 對象的年份值;4位年份。
* getMonth() :返回 Date 對象的月份值。從0開始,所以真實月份=返回值+1 。
* getDate() :返回 Date 對象的月份中的日期值;值的范圍1~31 。
* getHours() :返回 Date 對象的小時值。
* getMinutes() :返回 Date 對象的分鐘值。
* getSeconds() :返回 Date 對象的秒數值。
* getMilliseconds() :返回 Date 對象的毫秒值。
* getDay() :返回 Date 對象的一周中的星期值;0為星期天,1為星期一、2為星期二,依此類推
* getTime() :返回 Date 對象與'1970/01/01 00:00:00'之間的毫秒值(北京時間的時區為東8區,起點時間實際為:'1970/01/01 08:00:00') 。
### set 方法
* setFullYear(year, opt\_month, opt\_date) :設置 Date 對象的年份值;4位年份。
* setMonth(month, opt\_date) :設置 Date 對象的月份值。0表示1月,11表示12月。
* setDate(date) :設置 Date 對象的月份中的日期值;值的范圍1~31 。
\-setHours(hour, opt\_min, opt\_sec, opt\_msec) :設置 Date 對象的小時值。
* setMinutes(min, opt\_sec, opt\_msec) :設置 Date 對象的分鐘值。
* setSeconds(sec, opt\_msec) :設置 Date 對象的秒數值。
* setMilliseconds(msec) :設置 Date 對象的毫秒值。
### 其他方法
* toString() :將 Date 轉換為一個'年月日 時分秒'字符串
* toLocaleString() :將 Date 轉換為一個'年月日 時分秒'的本地格式字符串
* toDateString() :將 Date 轉換為一個'年月日'字符串
* toLocaleDateString() :將 Date 轉換為一個'年月日'的本地格式字符串
* toTimeString() :將 Date 轉換為一個'時分秒'字符串
* toLocaleTimeString() :將 Date 轉換為一個'時分秒'的本地格式字符串
* valueOf() :與getTime()一樣, 返回 Date 對象與'1970/01/01 00:00:00'之間的毫秒值(北京時間的時區為東8區,起點時間實際為:'1970/01/01 08:00:00')
### 靜態方法
#### Date.now()
說明:返回當前日期和時間的 Date 對象與'1970/01/01 00:00:00'之間的毫秒值(北京時間的時區為東8區,起點時間實際為:'1970/01/01 08:00:00') 參數:無
返回值:
{int} :當前時間與起始時間之間的毫秒數。
#### Date.parse(dateStr)
說明:把字符串轉換為 Date 對象 ,然后返回此 Date 對象與'1970/01/01 00:00:00'之間的毫秒值(北京時間的時區為東8區,起點時間實際為:'1970/01/01 08:00:00') 參數:
①dateStr {string} :可轉換為 Date 對象的字符串(可省略時間);字符串的格式主要有兩種:
1) yyyy/MM/dd HH:mm:ss (推薦):若省略時間,返回的 Date 對象的時間為 00:00:00。
2) yyyy-MM-dd HH:mm:ss :若省略時間,返回的 Date 對象的時間為 08:00:00(加上本地時區)。若不省略時間,此字符串在IE中返回NaN(非數字)!
返回值:
{int} 返回轉換后的Date對象與起始時間之間的毫秒數。
# 時區問題
## 如何獲取時區?
如果想在js中獲取一個日期的時區,可以直接使用 [Date.prototype.getTimezoneOffset()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset).
~~~
var dateLocal = new Date();
var date1 = new Date('August 19, 1975 23:15:30 GMT+07:00');
var date2 = new Date('August 19, 1975 23:15:30 GMT-02:00');
console.log(dateLocal.getTimezoneOffset());
console.log(date1.getTimezoneOffset());
console.log(date2.getTimezoneOffset());
// -480
// -480
// -480
~~~
`getTimezoneOffset`返回的結果,是當前地方時和UTC時間的差值,用分鐘表示。上述 `dateLocal` 可以理解為,`( 0時區 - 本地時區(+8) ) * 60min = -480`.
所以想獲得標準的時區,例如 +8 或 -8,需要進行以下處理:
~~~
// 使用原生 js
var date = new Date().getTimezoneOffset();
var timezone = -date;
console.log(timezone); // 480
console.log(timezone / 60); // 8
// 使用 moment (moment是基于local - utc得到的)
var date = moment();
var timezone = date.utcOffset();
console.log(timezone); // 480
console.log(timezone / 60); // 8
~~~
看到輸出結果,大家可能會問為什么 date1 和 date2 的輸出結果不是 +7 和 -2?
這個問題后面會為大家解答。
## 如何設置時區?
Date 對象提供了給實例 set 日期、時間的方法,但是并不支持修改實例的時區。
詳情可以參考 [Date.prototype 提供的方法](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)。
ISO標準類型有:
* `"2019-06-10"` (date-only form)
* `"2019-06-10T14:48:00"` (date-time form)
* `"2019-06-10T14:48:00.000+09:00"` (date-time form with milliseconds and time zone)
* `"2019-06-10T00:00:00.000Z"` (specifying UTC timezone via the ISO date specification,Z is the same with +00:00)
一些非ISO標準的類型:
* `Aug 9, 1995`
* `Wed, 09 Aug 1995 00:00:00`
* `Wed, 09 Aug 1995 00:00:00 GMT`
# 常見問題
## 實例化 Date 對象時傳入了時區,為什么獲取的時區是本地時區?
~~~
var date1 = new Date('August 19, 1975 23:15:30 GMT+07:00');
var date2 = new Date('August 19, 1975 23:15:30 GMT-02:00');
console.log(date1.getTimezoneOffset());
console.log(date2.getTimezoneOffset());
// -480
// -480
~~~
需要注意,不管你如何實例化一個 Date 對象,js在本地存儲時,都會將它轉換成本地時區。js 不會幫你存儲實例化該日期時的時區信息。
~~~
new Date('June 15, 2019 23:15:30 GMT+10:00');
// 東10區的時間,實例化成功后,日期被轉換成了本地時區
// Sat Jun 15 2019 21:15:30 GMT+0800 (中國標準時間)
~~~
那怎樣才能獲得一個攜帶了指定時區的日期對象呢?答案是,**JS原生日期對象并不支持**。
無法想象RD同學跟PM滿臉無辜的解釋"JS辦不到"之后,被PM追著砍的場景,因為還好[moment](https://momentjs.com/timezone/)支持了。
如下圖所示,直接聲明一個moment實例,并不會攜帶任何`offset`信息,因為這是一個 UTC 時間,只不過基于 js Date 的特性,直接`toDate`打印的結果會基于本地時區給你進行展示。
通過調用 `tz()` 方法,我們給一個moment實例指定了時區,這個時區是東京所在的 +9 區。這時能看到,這個moment實例擁有了`offset`屬性。繼續調用`format('Z')`,可以得到其時區為"+09:00".
## 如何處理 YYYY-MM-DD 這樣的日期字符串?
在js中,很多時候需要把日期字符串轉換為一個 Date 對象。如果得到的日期字符串有時間還好辦,如果就是一個`"2019-10-10"`這樣的字符串呢?
大部分人可能什么都沒想,直接就調用了 `new Date(datestring)`。可是事情沒有想象中那么簡單。讓我們來對比一下:
~~~
var date1 = new Date('2019-10-10')
// Thu Oct 10 2019 08:00:00 GMT+0800 (中國標準時間)
var date2 = new Date('2019-10-10 00:00:00')
// Thu Oct 10 2019 00:00:00 GMT+0800 (中國標準時間)
~~~
可以發現,直接輸入日期,和輸入日期+時間,得到的結果差了整整8個小時!
直接給new Date傳入'YYYY-MM-DD'這樣的字符串,得到的是一個基于UTC時間的Date實例。前文有說過,UTC時間即是0時區的標準時間。
所以上面的代碼例子中,`date1` 實例化時,內部先獲取到了一個`2019-10-10 00:00:00 GMT+00:00`這樣的時間,再被轉為本地時區,就多了8個小時。
而`date2`實例化時,`2019-10-10 00:00:00`被當做`GMT +08:00`的時區,所以得到的時間,就是0點。
這兩種方式沒有對與錯之分,但是使用的時候需要十分注意。個人不建議使用`new Date(YYYY-MM-DD)`這樣的方式。
說了一堆理論,到底哪些場景要注意問題呢?Show you the code:
~~~
// code is runningg on GMT +08:00
const d = new Date('2019-10-10');
const date = d.getDate();
// 10
// Looks good!
// code is runningg on GMT -10:00
const d = new Date('2019-10-10');
const date = d.getDate();
// 9
// Amazing?!
~~~
總結上面的代碼:在小于0時區的地方,直接用 new Date('YYYY-MM-DD') 這樣的方式實例化日期并且獲取日期,永遠會少一天。但是使用 new Date('YYYY-MM-DD 00:00:00') 就不會。
使用 moment 可以輕松的解決上述問題:
~~~
moment('2019-10-10').toDate()
// Thu Oct 10 2019 00:00:00 GMT+0800 (中國標準時間)
moment('2019-10-10 00:00:00').toDate()
// Thu Oct 10 2019 00:00:00 GMT+0800 (中國標準時間)
~~~
## 為什么 safari 調用 new Date 老報錯?
下面這段代碼確實會報錯:
~~~
new Date('2019-10-10 00:00:00')
// Invalid Date
復制代碼
~~~
老司機們可能知道safari一直以來都有上述bug,為了解決這個問題,可以使用以下代碼:
~~~
new Date('2019/10/10 00:00:00')
// Thu Oct 10 2019 00:00:00 GMT+0800 (CST)
~~~
## 有哪些好用的處理時區與日期的工具庫?
* [Moment.js](https://momentjs.com/) - Parse, validate, manipulate, and display dates and times in JavaScript
* [Moment Timezone](https://momentjs.com/timezone/) - Parse and display dates in any timezone
* [DAY.JS](https://github.com/iamkun/dayjs) - A minimalist JavaScript library for modern browsers with a largely Moment.js-compatible API
* [date-fns](https://date-fns.org/) - Modern JavaScript date utility library
- HTML
- 標簽
- 超鏈接
- 列表
- 表格和表單
- h5新增標簽
- 快捷方式
- 標簽包含
- CSS
- 選擇器
- 行內,塊元素,鏈接
- css三大特性
- 盒子模型
- 定位
- css可見性
- emment書寫
- 文本元素
- 外觀屬性
- 背景
- 浮動
- ps
- 用戶界面樣式
- 顯示和隱藏
- 過渡
- 2D,3D變形
- 動畫animation
- 伸縮布局(CSS3)
- BFC
- 優雅降級和漸進增強
- 3D旋轉
- 雙飛翼和圣杯
- JS基礎
- 輸出消息的幾種方式
- 數據類型
- Date對象
- Math對象
- Array對象
- 字符串常用方法
- 數據類型轉換
- 等號運算
- 代碼調試
- 數組
- 函數
- WebAPI
- webapi簡介
- 獲取頁面元素
- 事件
- 屬性操作
- 創建元素
- 節點操作
- 事件詳解
- BOM
- 位置相關屬性
- 拖拽彈窗
- 彈出層加遮罩
- ES6
- let和const
- 解構表達式變化
- 函數優化
- map和reduce
- nrm
- npm
- npm基礎
- package.json
- 淘寶鏡像
- webpack
- 介紹
- 多入口文件(Multiple entry files)
- Webpack CSS loader加載器
- webpack Image loader 加載圖片
- uglify-js壓縮打包JS
- webpack構建本地服務器
- vue內部指令
- v-if,v-show,v-for
- v-text,v-html
- v-on
- v-model
- v-bind
- v-pre,v-cloak,v-once
- vue全局api
- Vue.directive 自定義指令
- vue.extend構造器的延伸
- vue.set全局操作
- Vue的生命周期(鉤子函數)
- Template 制作模版
- Component 初識組件
- Component 組件props 屬性設置
- Component 父子組件關系
- Component 標簽
- vue選項
- propsData Option全局擴展數據傳遞
- computed Option 計算選項
- Methods Option 方法選項
- watch選項監控數據
- Mixins 混入選項操作
- Extends Option 擴展選項
- delimiters 選項
- vue實例和內置組件
- 實例屬性
- 實例方法
- 實例事件
- 內置組件 -slot
- vue-cli
- vue-cli介紹
- 項目目錄結構
- vue-cli模板
- vue-router
- 簡介
- 配置子路由
- 參數傳遞
- 單頁面多路由區域操作
- url傳遞參數
- vscode