Date comparison failure: expect(Date()).to(equal(Date())) inconsistent across locales
0 reputation · 04 Jan 2020, 03:25 UTC
0 reputation · 04 Jan 2020, 03:25 UTC
The goal is to assert that two Date instances parsed from identical ISO strings without explicit time zone information are equal across all environments.
Nimble compares dates via timeIntervalSinceReferenceDate, which is zone‑independent, but the parsing step is not; local locale differences can produce distinct Date values.
Because Nimble lacks a public API for specifying a time zone when asserting date equality, developers must manually normalize dates, raising portability concerns for CI pipelines.
1. Does Nimble provide any API to specify a time zone for date expectations?
2. Should Nimble automatically normalize parsed dates to UTC before comparison?
3. What impact do these choices have on tests that run on CI systems configured to UTC while developers run locally in other zones?
26525 reputation · 04 Jan 2020, 06:17 UTC
Nimble does not provide a built-in API to specify a time zone for date expectations. Because Nimble compares Date instances using timeIntervalSinceReferenceDate, the comparison itself is zone-independent; however, the instantiation of those dates from ISO strings without time zone offsets is not. When a string lacks an offset, the system parses it using the local time zone of the environment, leading to different absolute timestamps on a developer's machine versus a UTC-configured CI server.
The inconsistency is not a failure of the Nimble matcher, but a side effect of how DateFormatter or ISO8601DateFormatter behaves when the input string is "naive" (lacks a time zone). If the input is "2026-09-18T10:00:00", the system assumes the local time zone. A developer in EST and a CI server in UTC will produce two different Date objects representing different moments in absolute time, causing the equal() assertion to fail.
To ensure portability across environments, you must normalize the parsing logic rather than the assertion. Use one of the following approaches:
DateFormatter to UTC before creating the Date objects.Z (for UTC) or a specific offset (e.g., +05:00) to your test strings to remove ambiguity.expect().Tests that pass locally but fail in CI (or vice versa) are typically "flaky" due to this environmental dependency. Relying on the system locale makes tests non-deterministic. By forcing UTC parsing, you ensure that the timeIntervalSinceReferenceDate remains identical regardless of where the binary is executed.
To provide a more specific code snippet, please clarify: Which class are you using to parse the ISO strings (e.g., ISO8601DateFormatter, DateFormatter, or a third-party library)?
Use comments to ask for clarification. Post a solution as an answer.
26,525 reputation · 04 Jan 2020, 13:29 UTC
When you call Date() without new, the runtime returns a locale‑formatted string, e.g. Mon Aug 05 2024 14:32:10 GMT+0100 (British Summer Time). Two calls produce different strings if the process runs in different time‑zones or if LC_ALL changes, so expect(Date()).to(equal(Date())) will fail intermittently.
Using new Date() creates an actual Date instance. For a robust assertion you can compare the numeric time value:
expect(new Date().getTime()).toEqual(new Date().getTime());
Or use an ISO string, which is timezone‑independent:
expect(new Date().toISOString()).toEqual(new Date().toISOString());
Either approach normalizes the comparison and eliminates locale‑drift in CI pipelines.