> For the complete documentation index, see [llms.txt](https://mistborn.gitbook.io/til-coding/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mistborn.gitbook.io/til-coding/javascript/date-and-time.md).

# Date and time

內建的物件 Date，可以創造、改變、計算時間。

## Creation

* new Date()

  ```javascript
  let now = new Date();
  alert( now ); // shows current date/time
  ```
* new Date(milliseconds)

  ```javascript
  // 0 means 01.01.1970 UTC+0
  let Jan01_1970 = new Date(0);
  alert( Jan01_1970 );

  // now add 24 hours, get 02.01.1970 UTC+0
  let Jan02_1970 = new Date(24 * 3600 * 1000);
  alert( Jan02_1970 );
  ```
* new Date(datestring)

  ```javascript
  // string 用 Date.parse 轉換成時間
  let date = new Date("2017-01-26");
  alert(date);
  ```
* new Date(year, month, date, hours, minutes, seconds, ms)
  * The `year` must have 4 digits: `2013` is okay, `98` is not.
  * The `month` count starts with `0` (Jan), up to `11` (Dec).
  * The `date` parameter is actually the day of month, if absent then `1` is assumed.
  * If `hours/minutes/seconds/ms` is absent, they are assumed to be equal `0`.

    ```javascript
    new Date(2011, 0, 1, 0, 0, 0, 0); // // 1 Jan 2011, 00:00:00
    new Date(2011, 0, 1); // the same, hours etc are 0 by default

    let date = new Date(2011, 0, 1, 2, 3, 4, 567);
    alert( date ); // 1.01.2011, 02:03:04.567
    ```

## Access date components

* getFullYear() 取得年份
* &#x20;getMonth() 取得月份 0 - 11
* &#x20;getDate() 取得日期 1 - 31
* &#x20;getHours(), getMinutes(), getSeconds(), getMilliseconds() 取得對應的時間
* &#x20;getDay() 取得星期 0 (sunday) - 6 (saturday)
* 以上方法都是返回當地時間， getUTCFullYear(), getUTCMonth(), getUTCDay() 得到 UTC+0 時間
* &#x20;getTime() 從 1970-1-1 00:00:00 UTC+0 開始的 milliseconds
* &#x20;getTimezoneOffset() 返回跟 UTC+0 的時間差(分鐘)

  ```javascript
  // if you are in timezone UTC-1, outputs 60
  // if you are in timezone UTC+3, outputs -180
  alert( new Date().getTimezoneOffset() );
  ```

### [Setting date components](https://javascript.info/date#setting-date-components)

* setFullYear(year \[, month, date])
* setMonth(month \[, date])
* setDate(date)
* setHours(hour \[, min, sec, ms])
* setMinutes(min \[, sec, ms])
* setSeconds(sec \[, ms])
* setMilliseconds(ms)
* setTime(milliseconds) (sets the whole date by milliseconds since 01.01.1970 UTC)

除了 setTime() 都有 UTC+0 的時間。

```javascript
let today = new Date();

today.setHours(0);
alert(today); // still today, but the hour is changed to 0

today.setHours(0, 0, 0, 0);
alert(today); // still today, now 00:00:00 sharp.
```

## Autocorrection

```javascript
// date 有自動校對功能
let date = new Date(2013, 0, 32); // 32 Jan 2013 ?!?
alert(date); // ...is 1st Feb 2013!

// 不用思考是是否為閏月
let date = new Date(2016, 1, 28);
date.setDate(date.getDate() + 2);
alert( date ); // 1 Mar 2016

// 取得一段時間後的時間
let date = new Date();
date.setSeconds(date.getSeconds() + 70);
alert( date ); // shows the correct date

// 可以用零或負數
let date = new Date(2016, 0, 2); // 2 Jan 2016
date.setDate(1); // set day 1 of month
alert( date );
date.setDate(0); // min day is 1, so the last day of the previous month is assumed
alert( date ); // 31 Dec 2015
```

## Date to number, date diff

```javascript
// 時間轉換成數字，相當於用 date.getTime()
let date = new Date();
alert(+date); // the number of milliseconds, same as date.getTime()

// 日期可以相減，結果為 ms
let start = new Date(); // start counting
// do the job
for (let i = 0; i < 100000; i++) {
  let doSomething = i * i * i;
}
let end = new Date(); // done
alert( `The loop took ${end - start} ms` );
```

## Date.now()

```javascript
// 計算時間差，等同 new Date().getTime()，但沒有創造 Date 物件
let start = Date.now(); // milliseconds count from 1 Jan 1970
// do the job
for (let i = 0; i < 100000; i++) {
  let doSomething = i * i * i;
}
let end = Date.now(); // done
alert( `The loop took ${end - start} ms` ); // subtract numbers, not dates
```

## Benchmarking

```javascript
// we have date1 and date2, which function faster returns their difference in ms?
function diffSubtract(date1, date2) {
  return date2 - date1;
}

// or
function diffGetTime(date1, date2) {
  return date2.getTime() - date1.getTime();
}

// diffGetTime() 明顯快得多，因為沒有類型轉換，但這並不精確，因為執行 diffSubtract()時，CPU 可能在運行其他東西。
function diffSubtract(date1, date2) {
  return date2 - date1;
}

function diffGetTime(date1, date2) {
  return date2.getTime() - date1.getTime();
}

function bench(f) {
  let date1 = new Date(0);
  let date2 = new Date();

  let start = Date.now();
  for (let i = 0; i < 100000; i++) f(date1, date2);
  return Date.now() - start;
}

alert( 'Time of diffSubtract: ' + bench(diffSubtract) + 'ms' );
alert( 'Time of diffGetTime: ' + bench(diffGetTime) + 'ms' );

function diffSubtract(date1, date2) {
  return date2 - date1;
}

// 多測驗幾次可以增加準確度
function diffGetTime(date1, date2) {
  return date2.getTime() - date1.getTime();
}

function bench(f) {
  let date1 = new Date(0);
  let date2 = new Date();

  let start = Date.now();
  for (let i = 0; i < 100000; i++) f(date1, date2);
  return Date.now() - start;
}

let time1 = 0;
let time2 = 0;

// run bench(upperSlice) and bench(upperLoop) each 10 times alternating
for (let i = 0; i < 10; i++) {
  time1 += bench(diffSubtract);
  time2 += bench(diffGetTime);
}

alert( 'Total time for diffSubtract: ' + time1 );
alert( 'Total time for diffGetTime: ' + time2 );

// JavaScript 對執行很多次的程式碼有優化的效果，因此要將上一個加溫效果
// added for "heating up" prior to the main loop
bench(diffSubtract);
bench(diffGetTime);

// now benchmark
for (let i = 0; i < 10; i++) {
  time1 += bench(diffSubtract);
  time2 += bench(diffGetTime);
}
```

## Date.parse from a string

* `YYYY-MM-DD` – is the date: year-month-day.
* The character `"T"` is used as the delimiter.
* `HH:mm:ss.sss` – is the time: hours, minutes, seconds and milliseconds.
* The optional `'Z'` part denotes the time zone in the format `+-hh:mm`. A single letter `Z` that would mean UTC+0.

```javascript
let ms = Date.parse('2012-01-26T13:51:50.417-07:00');
alert(ms); // 1327611110417  (timestamp)

let date = new Date( Date.parse('2012-01-26T13:51:50.417-07:00') );
alert(date);
```
