Skip to content

Simplifying TIMESTAMP Queries with ?_loc=UTC #1345

@wjkoh

Description

@wjkoh

First and foremost, thank you for the excellent go-sqlite3 package! I use it frequently in my projects and truly appreciate the effort you've put into it. I have a quick suggestion I'd like to propose and would be interested to know if it makes sense.

As we know, storing and querying time.Time values in SQLite3 can be challenging. To make this easier, I've adopted a two-step approach. First, I enforce that every TIMESTAMP column stores only UTC timestamps.

I accomplish this using a CHECK constraint:

CREATE TABLE users(created TIMESTAMP CHECK(created LIKE concat(datetime(created), '%')));

This constraint ensures that only valid UTC timestamps are stored, as shown below:

sqlite> INSERT INTO users(created) VALUES('2025-07-27 03:37:44.556599+09:00');
Runtime error: CHECK constraint failed: created LIKE concat(datetime(created), '%') (19)
sqlite> INSERT INTO users(created) VALUES('2025-07-26 18:54:54.318724+00:00');
sqlite>

With this in place, we can safely assume that every TIMESTAMP field in our database is in the UTC timezone.

Second, when I query with time.Time values, I also have to ensure that they are in UTC. Currently, I have two options:

var start, end time.Time
// Option 1:
db.QueryContext(ctx, `SELECT * FROM users WHERE created >= datetime(?) AND created < datetime(?)`, start, end)
// Option 2:
db.QueryContext(ctx, `SELECT * FROM users WHERE created >= ? AND created < ?`, start.UTC(), end.UTC())

Unfortunately, neither of these options is ideal because it's easy to forget to call datetime() or .UTC(). I am hoping for a more automatic solution.

I noticed the ?_loc=UTC parameter for the Go sqlite3 driver, which at first glance seemed promising. As you know, however, it is currently only used for retrieving timestamp values from the database. I would like to propose extending this parameter to also automatically convert time.Time values to UTC when they are used in a query with created >= ?.

This change would significantly simplify the process and reduce the potential for errors. What are your thoughts on this suggestion?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions