當您在 Excel 和 Power BI 等工具中使用 Power Query 時,正確處理日期和時間值很重要,特別是當您的數據轉換相依於目前時間時。 Power Query 提供各種函式來擷取目前的日期和時間:
- DateTime.LocalNow
- DateTimeZone.LocalNow
- DateTime.FixedLocalNow
- DateTimeZone.FixedLocalNow
- DateTimeZone.UtcNow
- DateTimeZone.FixedUtcNow。
本文探討這些函式之間的差異,並釐清每個函式的使用時機和原因。 此外,它特彆強調一個重要但經常被忽視的細節。 Power Query Online 一律會傳回 UTC 時間,即使使用標示為「本機」的函式也一樣。瞭解這些細微差別可協助您避免非預期的結果,尤其是在建置時間敏感報表或自動化Power BI服務或Power Apps等應用程式中的數據更新時。
函式之間的差異
目前每個時間函式都有重要的差異。 這些函式會因時區感知、波動性而有所不同(在相同查詢中多次呼叫時的值是否變更),以及它們在不同環境中的行為方式(桌面與在線)。 下表包含每個函式的明細。
| 功能 | 退貨 | 揮發性 | 桌面行為 | 在線行為 | 典型的使用案例 |
|---|---|---|---|---|---|
DateTime.LocalNow |
datetime,表示目前當地時間 |
動態 - 每次在查詢評估期間叫用新的值時,都會傳回新的值 | 傳回本機電腦時間 | 傳回UTC時間 | 本地快速時間戳,無時區上下文 |
DateTimeZone.LocalNow |
值 datetimezone ,表示具有時區位移的目前當地時間 |
動態 - 每次在查詢評估期間叫用新的值時,都會傳回新的值 | 傳回當地時間與位移 | 傳回 UTC時間,具有 +00:00 偏移量 |
具有時區感知的當地時間 |
DateTime.FixedLocalNow |
datetime值,表示查詢評估期間第一次叫用時的當地時間 |
已修正 - 在整個單一查詢評估中傳回相同的值 | 第一次呼叫時擷取當地時間 | 擷取第一次呼叫時的 UTC 時間 | 沒有時區的當地時間快照 |
DateTimeZone.FixedLocalNow |
值 datetimezone ,表示在查詢評估期間第一次被叫用時的當地時間及其時差。 |
已修正 - 在整個單一查詢評估中傳回相同的值 | 在第一次呼叫時擷取具有位移的當地時間 | 在第一次呼叫時擷取具有+00:00偏移量的UTC時間 |
具有時區的當地時間快照集 |
DateTimeZone.UtcNow |
datetimezone值,表示目前的UTC時間 |
動態 - 每次在查詢評估期間叫用新的值時,都會傳回新的值 | 傳回目前的UTC時間 | 傳回目前的UTC時間 | 動態情境中的一致UTC時間戳 |
DateTimeZone.FixedUtcNow |
datetimezone值,表示查詢評估期間第一次叫用的UTC時間 |
已修正 - 在整個單一查詢評估中傳回相同的值 | 擷取第一次呼叫時的 UTC 時間 | 擷取第一次呼叫時的 UTC 時間 | 修正用於日誌記錄或稽核的UTC時間戳 |
在 Power Query M 中,選擇當地時間與以 UTC 為基礎的日期和時間函式,是影響查詢一致性、精確度和可移植性的重要設計決策。 類似 和 DateTime.LocalNow 的DateTime.FixedLocalNow函式在邏輯相依於本機系統時間時很有用,例如篩選「今日」發生的記錄,或產生使用者對向報表的時間戳。 這些函式會反映執行查詢的環境時區,使其適用於本機內容妥善定義的 Power Query Desktop 案例。
不過,在 Power Query Online 等分散式或雲端式環境中,這些相同的函式會傳回 UTC 時間,而不是使用者的實際當地時間。 如果您的邏輯假設當地時間內容,這種差異可能會導致細微的不一致。 相反地,DateTimeZone.UtcNow和DateTimeZone.FixedUtcNow提供一個在環境之間保持一致且不受日光節約時間或地區設定影響的時區中性參考點。 這些以UTC為基礎的函式是涉及數據整合、記錄、稽核或任何邏輯的首選,因為不論查詢執行的地點或時間如何,這些邏輯的行為都必須保持一致。
LocalNow 和 FixedLocalNow 函式之間的差異
Power Query M 提供四個函式來擷取目前的當地時間:
-
DateTime.LocalNow在每次求值時都返回當前本地的datetime。 -
DateTime.FixedLocalNow會針對每個查詢評估傳回本機datetime一次,作為快照。 -
DateTimeZone.LocalNow在每次求值時都返回當前本地的datetimezone。 -
DateTimeZone.FixedLocalNow每次查詢評估過程中傳回本機datetimezone,作為快照使用。
為了示範差異,下列範例會產生具有多個數據列的數據表。 每個數據列都會使用延遲來擷取新的 DateTime.LocalNow 值,以確保不同的時間戳,而每個擷 DateTime.FixedLocalNow 取的值都會在所有數據列之間維持不變。
備註
本文範例輸出中的所有日期和時間取決於函式執行的時間。 輸出中顯示的日期和時間僅供示範之用。
let
// Create a table with LocalNow and FixedLocalNow columns
TableWithTimes = Table.FromList(
{1..5},
each {
_,
Function.InvokeAfter(() => DateTime.LocalNow(), #duration(0, 0, 0, 0.2)),
Function.InvokeAfter(() => DateTime.FixedLocalNow(), #duration(0, 0, 0, 0.2))
},
{"Index", "LocalNow", "FixedLocalNow"}
),
// Format both datetime columns
FormatLocalNow = Table.TransformColumns(TableWithTimes,
{{"LocalNow", each DateTime.ToText(_, "yyyy-MM-ddThh:mm:ss.fff")}}),
FormatFixedNow = Table.TransformColumns(FormatLocalNow,
{{"FixedLocalNow", each DateTime.ToText(_, "yyyy-MM-ddThh:mm:ss.fff")}}),
// Change the table types
FinalTable = Table.TransformColumnTypes(FormatFixedNow, {{"Index", Int64.Type},
{"LocalNow", type text}, {"FixedLocalNow", type text}})
in
FinalTable
此範例的輸出如下:
如果您查看輸出,您可能會注意到,即使函式 DateTime.LocalNow 在程式碼中先出現,傳回 DateTime.FixedLocalNow 的值顯示的時間會比 DateTime.LocalTime 時間更早。 雖然 DateTime.LocalNow 在數據表建構中先列出,但 Power Query M 中的評估順序不保證會遵循數據表中的欄位順序。 相對於此,Power Query 使用延遲評估模型。 使用此模型表示欄位只會在需要時進行評估,且引擎會決定評估順序,而不是程式代碼中的順序。 在此情況下,會先評估 DateTime.FixedLocalNow 函式,因此第一次傳回此函式的時間會早於傳回 DateTime.LocalNow 的時間。
以下範例顯示如何使用DateTimeZone.LocalNow和DateTimeZone.FixedLocalNow來產生類似的結果。
let
// Create a table with LocalNow and FixedLocalNow columns
TableWithTimes = Table.FromList(
{1..5},
each {
_,
Function.InvokeAfter(() => DateTimeZone.LocalNow(), #duration(0, 0, 0, 0.2)),
Function.InvokeAfter(() => DateTimeZone.FixedLocalNow(), #duration(0, 0, 0, 0.2))
},
{"Index", "LocalNow", "FixedLocalNow"}
),
// Format both datetimezone columns
FormatLocalNow = Table.TransformColumns(TableWithTimes,
{{"LocalNow", each DateTimeZone.ToText(_, "yyyy-MM-ddThh:mm:ss.fff:zzz")}}),
FormatFixedNow = Table.TransformColumns(FormatLocalNow,
{{"FixedLocalNow", each DateTimeZone.ToText(_, "yyyy-MM-ddThh:mm:ss.fff:zzz")}}),
// Change the table types
FinalTable = Table.TransformColumnTypes(FormatFixedNow,
{{"Index", Int64.Type}, {"LocalNow", type text}, {"FixedLocalNow", type text}})
in
FinalTable
Power Query Desktop 中此範例的輸出如下:
備註
如果您在 Power Query Online 中執行此範例,傳回的時間一律為 UTC 時間,且傳回值的時區部分一律 +00:00為 。
UtcNow 與 FixedUtcNow 函式之間的差異
Power Query M 提供兩個函式來擷取目前的 UTC 時間:
-
DateTimeZone.UtcNow在每次評估表達式時,會返回當前的 UTCdatetimezone。 -
DateTimeZone.FixedUtcNow會針對每個查詢評估傳回本機datetimezone一次,作為快照。
這兩個函式之間的差異類似於 LocalNow 和 FixedLocalNow 函式。 不過,不論函式是在Power Query Desktop或Power Query Online 中執行,傳回值一律會以UTC時間傳回。 下列範例示範這兩個函式之間的差異。
let
// Create a table with UtcNow and FixedUtcNow columns
TableWithTimes = Table.FromList(
{1..5},
each {
_,
Function.InvokeAfter(() => DateTimeZone.UtcNow(), #duration(0, 0, 0, 0.2)),
Function.InvokeAfter(() => DateTimeZone.FixedUtcNow(), #duration(0, 0, 0, 0.2))
},
{"Index", "UtcNow", "FixedUtcNow"}
),
// Format both datetimezone columns
FormatLocalNow = Table.TransformColumns(TableWithTimes,
{{"UtcNow", each DateTimeZone.ToText(_, "yyyy-MM-ddThh:mm:ss.fff:zzz")}}),
FormatFixedNow = Table.TransformColumns(FormatLocalNow,
{{"FixedUtcNow", each DateTimeZone.ToText(_, "yyyy-MM-ddThh:mm:ss.fff:zzz")}}),
// Change the table types
FinalTable = Table.TransformColumnTypes(FormatFixedNow,
{{"Index", Int64.Type}, {"UtcNow", type text}, {"FixedUtcNow", type text}})
in
FinalTable
Power Query Desktop 和 Power Query Online 中此範例的輸出為:
對其他函式的影響
其他相依於目前日期和時間的 Power Query M 函式也會受到 Power Query Desktop 或 Power Query Online 上傳回當地時間的方式所影響。 例如,如果您使用DateTimeZone.ToLocal 函數將UTC時間轉換為當地時間,它在「Power Query Online」上仍然會返回UTC時間。
另一個範例是可以使用目前系統時間做為參數的任何函式。 這些函式包括Date.Month、Date.DayOfYear、DateTime.IsInCurrentYear、DateTimeZone.ZoneHours或任何其他可評估目前日期和時間的函式。
在所有這些函式中,如果您的邏輯取決於某個值是否落在目前日期、小時、月或年份內,則結果在環境之間可能會有所不同。 如果查詢在界限附近執行時,環境之間的這些差異特別明顯(例如,就在午夜前後、新月的開始或新年)。 如果不同環境之間的一致性很重要,請使用 DateTimeZone.UtcNow 或 DateTimeZone.FixedUtcNow 函式來擷取日期和時間。
最佳做法和建議
在 Power Query 中選擇正確的時間函式取決於您的特定使用案例、查詢執行所在的環境(桌面與在線),以及您是否需要動態或固定的時間戳。 以下是一些可協助引導您決策的最佳做法:
-
明確時區:當時區內容很重要時,請使用DateTimeZone函式,而不是DateTime函式。 在環境之間使用
DateTimeZone.UtcNow或DateTimeZone.FixedUtcNow來保持一致性,特別是在Power BI服務等雲端式解決方案中。 -
針對可重複的結果使用固定函式:當您希望時間戳在整個查詢評估中保持常數時,請使用固定變數(例如
DateTimeZone.FixedUtcNow)。 此方法特別適用於記錄、稽核或擷取數據輸入的時間。 -
避免 Power Query Online 中的本機函數:在 Power BI 服務等雲端解決方案中,像
DateTime.LocalNow和DateTimeZone.LocalNow這樣的函數返回 UTC 時間,這可能會導致混淆或不正確的假設。 如果您需要服務的實際當地時間,請考慮使用已知的位移手動調整 UTC(例如,由於日光節約時間或地區設定,這項調整可能很脆弱)。 - 在桌面和在線環境中進行測試:如果您的邏輯相依於目前時間,請一律在Power Query Desktop和Power Query Online 中測試您的查詢。 此測試有助於提早發現差異,特別是針對排程的重新整理情境。
- 記錄時間邏輯:清楚批注或記載為何使用特定時間函式,特別是當您使用時區處理的因應措施時。 此資訊可協助未來的共同作業者瞭解邏輯背後的意圖。
- 針對排程的工作流程使用UTC:針對排程的重新整理或自動化管線,UTC是最安全且最可預測的選擇。 它可避免因夏令時間或區域時區變動所造成的不確定性。
- 在需要時快取時間值:如果您需要在查詢中跨多個步驟使用相同的時間戳,請使用固定函式將它指派給查詢頂端的變數。 此變數可確保整個轉換邏輯的一致性。