question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Postgres `timetz` always stored in UTC

See original GitHub issue

Bug description

Currently, it seems any time you create a record with type timetz the time is automatically converted to be in UTC. In my case, I would like all of the database records to be stored in America/Chicago time zone, so I’m preparing the ISO string in that way before using the create method. However, prisma doesn’t respect this and converts the time back to UTC.

The create statement is below:

   console.log(timeEST) // 2021-06-28T12:00:00.000-05:00
    const course = await prisma.classes.create({
      data: {
        day_of_week,
        class_time: timeEST,
        instructors: { connect: { id: instructor } },
        class_types: { connect: { id: class_type } },
      },
    })

Database results all showing +0 zone:

 id | day_of_week | class_time  | instructor | class_type | virtual 
----+-------------+-------------+------------+------------+---------
 19 |           5 | 11:30:00+00 |          3 |          7 | t
 20 |           5 | 11:30:00+00 |          3 |          7 | t
 35 |           1 | 17:00:00+00 |          3 |          7 | t
 36 |           1 | 17:00:00+00 |          3 |          7 | t
 37 |           1 | 17:00:00+00 |          3 |          7 | t
 38 |           1 | 17:00:00+00 |          3 |          7 | t
(6 rows)

Model for this:

model classes {
  id            Int             @id @default(autoincrement())
  day_of_week   Int
  class_time    DateTime        @db.Timetz(6)
  instructor    Int
  class_type    Int
  virtual       Boolean?        @default(true)
  class_types   class_types     @relation(fields: [class_type], references: [id])
  instructors   instructors     @relation(fields: [instructor], references: [id])
  zoom_meetings zoom_meetings[]
}

How to reproduce

You can use the following SQL to reproduce the code I have above:

CREATE TABLE instructors (
    id serial,
    name text unique not null,
    image_url text unique not null,
    PRIMARY KEY (id)
);

CREATE TABLE class_types (
    id serial,
    name text not null,
    description text not null,
    duration integer not null,
    image_url text,
    PRIMARY KEY (id)
);

CREATE TABLE classes (
    id serial,
    day_of_week integer not null,
    class_time timetz not null,
    instructor integer not null,
    class_type integer not null,
    virtual boolean default true,
    PRIMARY KEY (id),
    FOREIGN KEY (instructor) REFERENCES instructors (id) ON DELETE cascade,
    FOREIGN KEY (class_type) REFERENCES class_types (id)
);

Expected behavior

If an ISO string is passed in with a timezone specified, it should keep that timezone instead of converting to UTC

Prisma information

Environment & setup

  • OS: Mac OS
  • Database:
    • Client: Postgres 13.3
    • Server: PostgreSQL 12.7 (Ubuntu 12.7-1.pgdg16.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609, 64-bit
  • Node.js version: v12.22.1

Prisma Version

prisma               : 2.25.0
@prisma/client       : 2.25.0
Current platform     : darwin
Query Engine         : query-engine c838e79f39885bc8e1611849b1eb28b5bb5bc922 (at node_modules/@prisma/engines/query-engine-darwin)
Migration Engine     : migration-engine-cli c838e79f39885bc8e1611849b1eb28b5bb5bc922 (at node_modules/@prisma/engines/migration-engine-darwin)
Introspection Engine : introspection-core c838e79f39885bc8e1611849b1eb28b5bb5bc922 (at node_modules/@prisma/engines/introspection-engine-darwin)
Format Binary        : prisma-fmt c838e79f39885bc8e1611849b1eb28b5bb5bc922 (at node_modules/@prisma/engines/prisma-fmt-darwin)
Default Engines Hash : c838e79f39885bc8e1611849b1eb28b5bb5bc922
Studio               : 0.402.0

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:4
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
ferjul17commented, Sep 10, 2021

Hi,

I think this is not a Prisma issue, but a PostgreSQL one.

As explained in their documentation:

For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system’s TimeZone parameter, and is converted to UTC using the offset for the timezone zone.

PostgreSQL does not store the timezone, and I do not expect Prisma to do it for me.

I think the issue can be closed.

1reaction
giraffesyocommented, Feb 9, 2022

Hi,

I think this is not a Prisma issue, but a PostgreSQL one.

As explained in their documentation:

For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system’s TimeZone parameter, and is converted to UTC using the offset for the timezone zone.

PostgreSQL does not store the timezone, and I do not expect Prisma to do it for me.

I think the issue can be closed.

Postgres supports storing a time zone. The way postgres internally stores the time string isn’t important because it also stores the time zone specified. When you query the record from the database it includes the associated time zone information in the result but Prisma drops it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Documentation: 15: 8.5. Date/Time Types - PostgreSQL
For timestamp with time zone , the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time,...
Read more >
Time, TIMETZ, Timestamp and TimestampTZ in PostgreSQL
It does not store time zones, or change based on the session time zone. Another way to think about it is that it...
Read more >
Always Use TIMESTAMP WITH TIME ZONE - Just a Theory
They store values as UTC, but convert them on selection to whatever your time zone setting is. Avoid timestamp without time zone (aka...
Read more >
Any downside to using timestamp without time zone if UTC is ...
I would still suggest timestamptz . Here are some reasons: 1. timestamptz literally is the "preferred type" among date/time types in Postgres.
Read more >
Date and time in UTC - how to store them in postgres?
When a timestamp with time zone value is output, it is always converted from UTC to the current timezone zone, and displayed as...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found