Best way to work with dates in Android SQLite
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
SQLite does not have a dedicated date type, so the best way to store dates on Android is to choose one representation and keep it consistent across inserts, queries, and UI formatting. For most app code, the strongest default is an INTEGER column containing UTC epoch milliseconds. It is compact, easy to compare, and maps cleanly to modern Java and Kotlin time APIs.
Why Epoch Milliseconds Are a Strong Default
SQLite can store time-like values as text, real numbers, or integers. On Android, INTEGER epoch time is often the most practical because it gives you:
- simple numeric range queries
- timezone-neutral storage in UTC
- fast ordering and indexing
- easy conversion to
Instant,LocalDateTime, orZonedDateTime
The most important design rule is this: store in UTC, format for the user later.
Define the Table With an Integer Column
A basic schema looks like this:
This makes the meaning explicit. The column is not "some date string." It is a UTC timestamp in milliseconds.
Insert Dates From Kotlin
With modern Android code, work with Instant or epoch milliseconds rather than building manual date strings.
That keeps the database layer stable and avoids locale formatting issues.
Read Dates Back Into Time Objects
This is the right separation of concerns:
- database stores neutral UTC time
- app converts for the device timezone only when presenting to users
Query by Date Range Efficiently
Numeric timestamps make range queries straightforward.
This is cleaner and usually more index-friendly than parsing textual date formats at query time.
When ISO 8601 Text Is Still Reasonable
Text dates are not wrong. They can be a good choice when you need human-readable raw rows or easy interoperability with external data.
A good text format is ISO 8601 in UTC, for example:
If you choose text, be strict and keep the format uniform. Do not mix local time strings, human-readable display text, and machine-sortable timestamps in the same column.
For most Android apps, integer UTC timestamps are still easier to keep correct.
Avoid Legacy Date Handling Patterns
Older Android code often used java.util.Date, Calendar, and ad hoc SimpleDateFormat logic everywhere. Those APIs still exist, but they make timezone bugs and parsing mistakes more likely.
If your minSdk or toolchain allows it, prefer java.time APIs or their Android-compatible equivalents through desugaring. The code is clearer and the UTC story is easier to reason about.
Formatting for Display Is a Separate Step
Do not store user-facing formatted text such as "Mar 7, 2026 at 10:30 AM" in SQLite for actual date logic. That text is for UI only.
Store UTC timestamps, then format them near the UI layer:
That keeps persistence logic and presentation logic separate.
Common Pitfalls
- Storing local-time strings and later trying to compare them like real timestamps.
- Mixing several date formats in one table.
- Doing timezone conversion at insert time instead of storing UTC consistently.
- Using formatted display strings as the primary persisted date value.
- Forgetting that SQLite does not enforce a dedicated date column type for you.
Summary
- The best general-purpose Android SQLite date format is usually UTC epoch milliseconds in an
INTEGERcolumn. - Store neutrally, then format for the user's timezone at the UI layer.
- Numeric timestamps make ordering and range queries simple.
- ISO 8601 text is viable, but only if you keep it strict and consistent.
- Date correctness depends more on a stable storage contract than on SQLite itself.

