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.

PGTZ environment variable is not respected

See original GitHub issue
  • asyncpg version: 0.27.0
  • PostgreSQL version: 14.5
  • Do you use a PostgreSQL SaaS? If so, which? Can you reproduce the issue with a local PostgreSQL install?: Not SaaS
  • Python version: 3.11.0
  • Platform: macOS
  • Do you use pgbouncer?: bi
  • Did you install asyncpg with pip?: yes
  • If you built asyncpg locally, which version of Cython did you use?: Install by wheel
  • Can the issue be reproduced under both asyncio and uvloop?: Yes

Setting PGTZ environment variable does not affect the timezone returned, for example, select now().

Issue Analytics

  • State:closed
  • Created 10 months ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
elpranscommented, Dec 3, 2022

Those environment variables are specifically for libpq. Unlike psycopg2/psycopg3, asyncpg is NOT based on libpq. We do try to maintain a certain level of compatibility with libpq, on a best effort basis. In this particular case it’s tricky because PGTZ and SET timezone only affect text representaion of dates, while asyncpg uses binary I/O in which Postgres always returns as a UTC timestamp for timestamp with time zone. So, any timezone manipulation would have to be done on the client side, but that is also problematic, because supporting PGTZ would require a dependency on a timezone-capable library like dateutil, which I’m reluctant to add just for this.

The good news is that asyncpg is flexible enough to let you implement this yourself. Here’s a complete example using dateutil:

import asyncio
import datetime
import os

import asyncpg
import dateutil.tz

pg_epoch_datetime_utc = datetime.datetime(
    2000, 1, 1, tzinfo=datetime.timezone.utc)


async def main():
    con = await asyncpg.connect(user='postgres')

    def tz_aware_decoder(ts_tuple):
        # Decode timestamptz as usual, microseconds
        # relative to January 1, 2000 UTC.
        microseconds = ts_tuple[0]
        seconds = microseconds // 1000000
        microseconds %= 1000000

        delta = datetime.timedelta(0, seconds, microseconds)
        dt = pg_epoch_datetime_utc + delta

        # Adjust the result to PGTZ if set
        tz_str = os.environ.get("PGTZ")
        if tz_str:
            tz = dateutil.tz.gettz(tz_str)
            dt = dt.astimezone(tz)

        return dt

    def tz_encoder(dt):
        utc_dt = dt.astimezone(datetime.timezone.utc)
        delta = utc_dt - pg_epoch_datetime_utc
        seconds = delta.days * 86400 + delta.seconds
        microseconds = delta.microseconds
        return (seconds * 1000000 + microseconds,)

    await con.set_type_codec(
        'timestamptz',
        schema='pg_catalog',
        decoder=tz_aware_decoder,
        encoder=tz_encoder,
        format='tuple',
    )

    result = await con.fetchval("SELECT now()")
    print(result)
    await con.close()

asyncio.run(main())
0reactions
kigawascommented, Dec 3, 2022

No matter how minor it is, bug is bug.

I also tested with psycopg3 and it does recognize the PGTZ environment variable.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Documentation: 15: 34.15. Environment Variables - PostgreSQL
The following environment variables can be used to select default connection parameter values, which will be used by PQconnectdb , PQsetdbLogin and PQsetdb ......
Read more >
Greenplum Environment Variables
The following are standard PostgreSQL environment variables, which are also recognized in Greenplum Database. You may want to add the connection-related ...
Read more >
Unsupported timezone "localtime" when using the NodaTime ...
It looks like the localtime value must be set from here: var timezone = Settings.Timezone ?? Environment.GetEnvironmentVariable("PGTZ"); if ...
Read more >
Databases - Practical PostgreSQL - Date and Time Types
If the PGTZ environment variable is set, it can be read by any client written with libpq and interpreted as the client's default...
Read more >
How to set timezone for Postgres psql? - Stack Overflow
So, it seems you must either use the SET command inside psql, or either set the PGTZ environment variable: PGTZ=PST8PDT psql -c 'show ......
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