---
title: "Keep the time zone on every time · Agent Wranglers"
url: https://agentwranglers.se/playbook/architecture/data-shapes/zone-aware-times
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Keep the time zone on every time

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Data shapes](https://agentwranglers.se/playbook/architecture/data-shapes.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

- ID: ARC-72
- Level: Recommended
- Chapter: [Data shapes](https://agentwranglers.se/playbook/architecture/data-shapes)
- Rule: Inside the code, hold every moment in time as a type that carries its zone or offset, normally UTC. Never pass around a date and time without a zone.
- How: A time without a zone could be UTC or any local time, and code that mixes the two is off by hours. Python calls these "naive" objects and deprecated `datetime.utcnow()` in version 3.12 because it returns one. Create times with an explicit zone, such as `datetime.now(UTC)` in Python or `Instant.now()` in Java. Convert to local time only for display. Columns follow [exact types](https://agentwranglers.se/playbook/data/schema-design/exact-types), and the API follows [dates and times](https://agentwranglers.se/playbook/api-design/requests-and-responses/dates-and-times).
- Check: A linter fails time calls without a zone. Examples are Ruff's `DTZ` rules for Python and the Error Prone check `JavaTimeDefaultTimeZone` for Java. A test runs the suite with the machine set to two zones, such as `TZ=UTC` and `TZ=Pacific/Auckland`, and both pass.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### Python example

```python
# Bad: naive, so nobody knows which zone this is
created_at = datetime.utcnow()

# Good: aware, so comparisons and conversions are exact
created_at = datetime.now(UTC)
```

### Java example

```java
// Bad: LocalDateTime has no zone, so it depends on the server
LocalDateTime createdAt = LocalDateTime.now();

// Good: an Instant is one exact moment
Instant createdAt = Instant.now();
```

## Sources

- [Python datetime: aware and naive objects](https://docs.python.org/3/library/datetime.html#aware-and-naive-objects)

## Related rules

- [Choose exact types](https://agentwranglers.se/playbook/data/schema-design/exact-types) in Data
- [Send dates as RFC 3339 with a time zone](https://agentwranglers.se/playbook/api-design/requests-and-responses/dates-and-times) in API design
- [Test times at the daylight saving changes](https://agentwranglers.se/playbook/testing/unit-tests/daylight-saving-tests) in Testing

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/architecture/data-shapes/zone-aware-times">Agent Wranglers architecture playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Keep equality and hashing in step](https://agentwranglers.se/playbook/architecture/data-shapes/equality-and-hash)
- Next: [Compare decimal fractions with a tolerance](https://agentwranglers.se/playbook/architecture/data-shapes/float-comparison)
- [Data shapes](https://agentwranglers.se/playbook/architecture/data-shapes)
