d3-time
在視覺化時間序列資料、分析時間模式或一般處理時間時,傳統時間單位的差異會很快變得明顯。例如,在 格里曆 中,大多數月份有 31 天,但有些月份有 28、29 或 30 天;大多數年份有 365 天,但 閏年 有 366 天;加上 夏令時間,大多數天有 24 小時,但有些天有 23 或 25 小時。更複雜的是,夏令時間慣例在世界各地有所不同。
由於這些時間上的特殊性,執行一些看似微不足道的任務可能會很困難。例如,如果您想計算兩個日期之間經過的天數,您不能僅僅相減並除以 24 小時(86,400,000 毫秒)
const start = new Date(2015, 02, 01); // 2015-03-01T00:00
const end = new Date(2015, 03, 01); // 2015-04-01T00:00
const days = (end - start) / 864e5; // 30.958333333333332, oops! 🤯
不過,您可以使用 d3.timeDay.count
d3.timeDay.count(start, end) // 31 😌
d3-time 提供的 day interval 是其中之一。每個 interval 代表一個慣用的時間單位,例如 hours、weeks、months 等,並有方法計算邊界日期。例如,d3.timeDay 計算對應日期的午夜(通常是當地時間凌晨 12:00)。除了 rounding 和 counting,interval 也可以用來產生邊界日期陣列。例如,要計算當前月份的每個星期日
const start = d3.timeMonth.floor(new Date(2015, 0, 15)); // 2015-01-01T00:00
const stop = d3.timeMonth.ceil(new Date(2015, 0, 15)); // 2015-02-01T00:00
const weeks = d3.timeWeek.range(start, stop); // [2015-01-04T00:00, 2015-01-11T00:00, 2015-01-18T00:00, 2015-01-25T00:00]
d3-time 模組不會實作自己的日曆系統;它只是在 ECMAScript Date 的基礎上實作一個方便的日曆數學 API。因此,它會忽略閏秒,而且只能使用當地時區和 世界協調時間 (UTC)。
這個模組由 D3 的時間比例用來產生合理的刻度,由 D3 的時間格式使用,也可以直接用來執行類似 日曆配置 的工作。
interval(date)
d3.utcMonday() // the latest preceding Monday, UTC time
原始碼 · 等同於 interval.floor,但如果未指定 date,它會預設為目前時間。例如,d3.timeYear(date) 和 d3.timeYear.floor(date) 是等同的。
interval.floor(date)
d3.utcMonday.floor(new Date()) // the latest preceding Monday, UTC time
原始碼 · 傳回一個新的日期,代表在 date 之前或等於 date 的最新 interval 邊界日期。例如,d3.timeDay.floor(date) 通常會傳回給定 date 的當地時間凌晨 12:00。
這個方法是冪等的:如果指定的 date 已根據目前的 interval 進行取下限,則會傳回一個時間相同的日期。此外,傳回的日期是相關 interval 的最小可表達值,因此 interval.floor(interval.floor(date) - 1) 會傳回前一個 interval 邊界日期。
請注意,==
和 ===
運算子不會根據 Date 物件的值進行比較,因此您無法使用它們來判斷指定的日期是否已經取整。請改為強制轉換為數字,然後再進行比較
// Returns true if the specified date is a day boundary.
function isDay(date) {
return +d3.timeDay.floor(date) === +date;
}
這比測試時間是否為上午 12:00 更可靠,因為在某些時區中,由於夏令時間,可能不存在午夜。
interval.round(date)
d3.utcMonday.round(new Date()) // the previous or following Monday, whichever is closer
原始碼 · 傳回一個新的日期,代表最接近 date 的區間邊界日期。例如,d3.timeDay.round(date) 通常會在給定的 date 上傳回當地時間上午 12:00,如果在中午或中午之前,則傳回隔天的上午 12:00。
這個方法是冪等的:如果指定的 date 已經取整到目前的區間,則會傳回一個時間相同的日期。
interval.ceil(date)
d3.utcMonday.ceil(new Date()) // the following Monday
原始碼 · 傳回一個新的日期,代表大於或等於 date 的最早區間邊界日期。例如,d3.timeDay.ceil(date) 通常會在給定的 date 之後的日期上傳回當地時間上午 12:00。
這個方法是冪等的:如果指定的 date 已經取上界到目前的區間,則會傳回一個時間相同的日期。此外,傳回的日期是關聯區間的最大可表示值,例如 interval.ceil(interval.ceil(date) + 1) 會傳回下一個區間邊界日期。
interval.offset(date, step)
d3.utcDay.offset(new Date(), 1) // the same time tomorrow
原始碼 · 傳回一個新的日期,等於 date 加上 step 個間隔。如果未指定 step,則預設為 1。如果 step 為負值,則傳回的日期會在指定的 date 之前;如果 step 為 0,則傳回指定的 date 的一份拷貝;如果 step 不是整數,則會將其 取整。此方法不會將指定的 date 四捨五入到間隔。例如,如果 date 是今天下午 5:34,則 d3.timeDay.offset(date, 1) 會傳回明天下午 5:34(即使有日光節約時間變更!)。
interval.range(start, stop, step)
d3.utcDay.range(new Date("2014-01-01"), new Date("2015-01-01")) // every day in 2014
原始碼 · 傳回一個日期陣列,表示在 start(含)之後或在 stop(不含)之前的所有間隔邊界。如果指定了 step,則會傳回每個第 step 個邊界;例如,對於 d3.timeDay 間隔,step 為 2 會傳回每隔一天。如果 step 不是整數,則會將其 取整。
傳回陣列中的第一個日期是在 start 之後或與之相等的最近邊界;後續日期會以 step 個間隔 偏移 並 取整。因此,兩個重疊的範圍可能是相容的。例如,此範圍包含奇數日
d3.timeDay.range(new Date(2015, 0, 1), new Date(2015, 0, 7), 2) // [2015-01-01T00:00, 2015-01-03T00:00, 2015-01-05T00:00]
而此範圍包含偶數日
d3.timeDay.range(new Date(2015, 0, 2), new Date(2015, 0, 8), 2) // [2015-01-02T00:00, 2015-01-04T00:00, 2015-01-06T00:00]
若要讓範圍在指定 step 時相容,請改用 interval.every。
為方便起見,interval.range 的別名也會提供為對應間隔的複數形式,例如 utcMondays。
interval.filter(test)
原始碼 · 傳回一個新的間隔,它是使用指定的 test 函數對此間隔進行過濾的子集。test 函數會傳入一個日期,並且應該在且僅在指定的日期應視為間隔的一部分時傳回 true。例如,若要建立一個間隔,傳回每個月的 1 日、11 日、21 日和 31 日(如果存在)
d3.timeDay.filter((d) => (d.getDate() - 1) % 10 === 0)
傳回的過濾間隔不支援 interval.count。另請參閱 interval.every。
interval.every(step)
d3.unixDay.every(3)
原始碼 · 傳回此區間的已過濾檢視,代表每個步驟日期。步驟的意義取決於此區間的父區間,由欄位函數定義。例如,d3.timeMinute.every(15) 傳回一個代表每十五分鐘的區間,從整點開始::00、:15、:30、:45 等。請注意,對於某些區間,產生的日期可能不會均勻分佈;d3.timeDay 的父區間是 d3.timeMonth,因此區間號碼會在每個月初重設。如果步驟無效,則傳回 null。如果步驟為一,則傳回此區間。
此方法可與 interval.range 結合使用,以確保兩個重疊的範圍一致。例如,此範圍包含奇數日
d3.timeDay.every(2).range(new Date(2015, 0, 1), new Date(2015, 0, 7)) // [2015-01-01T00:00, 2015-01-03T00:00, 2015-01-05T00:00]
此範圍也包含奇數日
d3.timeDay.every(2).range(new Date(2015, 0, 2), new Date(2015, 0, 8)) // [2015-01-03T00:00, 2015-01-05T00:00, 2015-01-07T00:00]
傳回的已過濾區間不支援 interval.count。另請參閱 interval.filter。
interval.count(start, end)
原始碼 · 傳回開始(不含)之後且在結束(含)之前或等於結束的區間邊界的數量。請注意,此行為與 interval.range 稍有不同,因為它的目的是傳回指定的結束日期相對於指定的開始日期的零為基準的數字。例如,要計算目前的零為基準的年度日數
d3.timeDay.count(d3.timeYear(now), now) // 177
同樣地,要計算從星期日開始的星期數的目前的零為基準的星期數
d3.timeSunday.count(d3.timeYear(now), now) // 25
timeInterval(floor, offset, count, field)
const utcDay = d3.timeInterval(
(date) => date.setUTCHours(0, 0, 0, 0), // floor
(date, step) => date.setUTCDate(date.getUTCDate() + step), // offset
(start, end) => (end - start) / 864e5, // count
(date) => date.getUTCDate() - 1 // field
);
原始碼 · 根據指定的floor 和 offset 函數以及一個選用的count 函數建構一個新的自訂區間。
floor 函數將一個日期作為引數,並將其向下取整至最近的區間邊界。
offset 函數將一個日期和一個整數步驟作為引數,並將指定的日期向前推進指定的邊界數量;步驟可以是正數、負數或零。
選用的count 函數將一個開始日期和一個結束日期(已取整至目前的區間)作為引數,並傳回開始(不含)和結束(含)之間的邊界數量。如果未指定count 函數,則傳回的區間不會公開 interval.count 或 interval.every 方法。注意:由於內部最佳化,指定的count 函數不得在其他時間區間上呼叫 interval.count。
可選的 field 函數會接收一個日期,已取整至目前的區間,並傳回指定日期的欄位值,對應於此日期(不包含)與最近的先前父欄位邊界之間的邊界數目。例如,對於 d3.timeDay 區間,這會傳回自月份開頭以來的日數。如果未指定 field 函數,它會預設計算自 1970 年 1 月 1 日 UTC 的 UNIX 紀元以來的區間邊界數目。field 函數會定義 interval.every 的行為。
timeMillisecond
來源 · 本地時間的毫秒數;最短可用的時間單位。
timeSecond
來源 · 本地時間的秒數(例如,上午 01:23:45.0000);1,000 毫秒。
timeMinute
來源 · 本地時間的分鐘數(例如,上午 01:02:00);60 秒。請注意,ECMAScript 會忽略閏秒。
timeHour
來源 · 本地時間的小時數(例如,上午 01:00);60 分鐘。請注意,在本地時間中將時間提前一小時,可能會傳回相同的小時數或跳過一小時,這是因為夏令時間的關係。
timeDay
來源 · 本地時間的天數(例如,2012 年 2 月 7 日上午 12:00);通常為 24 小時。本地時間的天數可能介於 23 到 25 小時之間,這是因為夏令時間的關係。d3.unixDay 類似於 d3.utcDay,但它會計算自 UNIX 紀元(1970 年 1 月 1 日)以來的日數,因此 interval.every 會傳回間隔均勻的日期,而不是根據每月的天數而有所不同。
timeWeek
來源 · d3.timeSunday 的別名;7 天,通常為 168 小時。本地時間的週數可能介於 167 到 169 小時之間,這是因為夏令時間的關係。
timeSunday
來源 · 本地時間中以星期日為基準的週數(例如,2012 年 2 月 5 日上午 12:00)。
timeMonday
來源 · 本地時間中以星期一為基準的週數(例如,2012 年 2 月 6 日上午 12:00)。
timeTuesday
來源 · 以星期二為基礎的當地時間週(例如 2012 年 2 月 7 日上午 12:00)。
timeWednesday
來源 · 以星期三為基礎的當地時間週(例如 2012 年 2 月 8 日上午 12:00)。
timeThursday
來源 · 以星期四為基礎的當地時間週(例如 2012 年 2 月 9 日上午 12:00)。
timeFriday
來源 · 以星期五為基礎的當地時間週(例如 2012 年 2 月 10 日上午 12:00)。
timeSaturday
來源 · 以星期六為基礎的當地時間週(例如 2012 年 2 月 11 日上午 12:00)。
timeMonth
來源 · 當地時間月份(例如 2012 年 2 月 1 日上午 12:00);範圍為 28 至 31 天。
timeYear
來源 · 當地時間年份(例如 2012 年 1 月 1 日上午 12:00);範圍為 365 至 366 天。
utcMillisecond
來源 · UTC 時間毫秒;最短的時間單位。
utcSecond
來源 · UTC 時間秒(例如 上午 01:23:45.0000);1,000 毫秒。
utcMinute
來源 · UTC 時間分(例如 上午 01:02:00);60 秒。請注意,ECMAScript 忽略閏秒。
utcHour
原始碼 · UTC 時間的小時 (例如,凌晨 01:00);60 分鐘。
utcDay
原始碼 · UTC 時間的天 (例如,2012 年 2 月 7 日凌晨 12:00);24 小時。
utcWeek
原始碼 · d3.timeSunday 的別名;7 天和 168 小時。
utcSunday
原始碼 · UTC 時間的星期日為基礎的星期 (例如,2012 年 2 月 5 日凌晨 12:00)。
utcMonday
原始碼 · UTC 時間的星期一為基礎的星期 (例如,2012 年 2 月 6 日凌晨 12:00)。
utcTuesday
原始碼 · UTC 時間的星期二為基礎的星期 (例如,2012 年 2 月 7 日凌晨 12:00)。
utcWednesday
原始碼 · UTC 時間的星期三為基礎的星期 (例如,2012 年 2 月 8 日凌晨 12:00)。
utcThursday
原始碼 · UTC 時間的星期四為基礎的星期 (例如,2012 年 2 月 9 日凌晨 12:00)。
utcFriday
原始碼 · UTC 時間的星期五為基礎的星期 (例如,2012 年 2 月 10 日凌晨 12:00)。
utcSaturday
原始碼 · UTC 時間的星期六為基礎的星期 (例如,2012 年 2 月 11 日凌晨 12:00)。
utcMonth
原始碼 · UTC 時間的月份 (例如,2012 年 2 月 1 日凌晨 12:00);範圍從 28 到 31 天。
utcYear
來源 · UTC 時間中的年份(例如,2012 年 1 月 1 日上午 12:00);範圍從 365 天到 366 天。
unixDay
類似於 d3.utcDay,不同之處在於它計算自 UNIX 紀元(1970 年 1 月 1 日)以來的日子,使得 interval.every 會傳回間隔均勻的日期,而不是根據每個月的天數而有所不同。
timeMilliseconds(start, stop, step)
d3.timeMillisecond.range 的別名。
timeSeconds(start, stop, step)
d3.timeSecond.range 的別名。
timeMinutes(start, stop, step)
d3.timeMinute.range 的別名。
timeHours(start, stop, step)
d3.timeHour.range 的別名。
timeDays(start, stop, step)
d3.timeDay.range 的別名。
timeWeeks(start, stop, step)
d3.timeWeek.range 的別名。
timeSundays(start, stop, step)
d3.timeSunday.range 的別名。
timeMondays(start, stop, step)
d3.timeMonday.range 的別名。
timeTuesdays(start, stop, step)
d3.timeTuesday.range 的別名。
timeWednesdays(start, stop, step)
別名為 d3.timeWednesday.range。
timeThursdays(start, stop, step)
別名為 d3.timeThursday.range。
timeFridays(start, stop, step)
別名為 d3.timeFriday.range。
timeSaturdays(start, stop, step)
別名為 d3.timeSaturday.range。
timeMonths(start, stop, step)
別名為 d3.timeMonth.range。
timeYears(start, stop, step)
別名為 d3.timeYear.range。
utcMilliseconds(start, stop, step)
別名為 d3.utcMillisecond.range。
utcSeconds(start, stop, step)
別名為 d3.utcSecond.range。
utcMinutes(start, stop, step)
別名為 d3.utcMinute.range。
utcHours(start, stop, step)
別名為 d3.utcHour.range。
utcDays(start, stop, step)
utcWeeks(start, stop, step)
別名為 d3.utcWeek.range。
utcSundays(start, stop, step)
別名為 d3.utcSunday.range。
utcMondays(start, stop, step)
別名為 d3.utcMonday.range。
utcTuesdays(start, stop, step)
別名為 d3.utcTuesday.range。
utcWednesdays(開始, 停止, 步長)
別名為 d3.utcWednesday.範圍。
utcThursdays(開始, 停止, 步長)
別名為 d3.utcThursday.範圍。
utcFridays(開始, 停止, 步長)
別名為 d3.utcFriday.範圍。
utcSaturdays(開始, 停止, 步長)
別名為 d3.utcSaturday.範圍。
utcMonths(開始, 停止, 步長)
別名為 d3.utcMonth.範圍。
utcYears(開始, 停止, 步長)
別名為 d3.utcYear.範圍。
timeTicks(開始, 停止, 計數)
來源 · 等同於 d3.utcTicks,但以當地時間表示。
timeTickInterval(開始, 停止, 計數)
來源 · 傳回 d3.timeTicks 在給定相同參數時會使用的時間間隔。
utcTicks(開始, 停止, 計數)
來源 · 傳回一個陣列,其中包含大約 計數 個日期,這些日期在 開始 和 停止(包含)之間以規則的間隔出現。如果 停止 早於 開始,則日期會以反向時間順序傳回;否則,日期會以時間順序傳回。考量下列 UTC 時間間隔
- 1 秒
- 5 秒
- 15 秒
- 30 秒
- 1 分鐘
- 5 分鐘
- 15 分鐘
- 30 分鐘
- 1 小時
- 3 小時
- 6 小時
- 12 小時
- 1 天
- 2 天
- 1 週
- 1 個月
- 3 個月
- 1 年
也會考量毫秒的倍數(對於小範圍)和年(對於大範圍),遵循 d3.ticks 的規則。使用產生最接近 count 的日期數量的區間。例如
const start = new Date("1970-03-01");
const stop = new Date("1996-03-19");
const count = 4;
const ticks = d3.utcTicks(start, stop, count); // [1975-01-01, 1980-01-01, 1985-01-01, 1990-01-01, 1995-01-01]
如果 count 是時間區間,此函數的行為類似於 interval.range,但 start 和 stop 都是包含的,如果 stop 在 start 之前,它可能會按反向時間順序傳回日期。
utcTickInterval(start, stop, count)
來源 · 傳回 d3.utcTicks 會在給定相同引數的情況下使用的時間區間。如果沒有關聯的區間,例如當 start 或 stop 無效時,傳回 null。
const start = new Date("1970-03-01");
const stop = new Date("1996-03-19");
const count = 4;
const interval = d3.utcTickInterval(start, stop, count); // d3.utcYear.every(5)