PostgreSQL Timezone Mismatch: Fixing GMT Instead of System Timezone (Europe/Vienna)


3 views

When PostgreSQL shows GMT despite your system being configured for Europe/Vienna, it typically indicates one of these scenarios:

  • Environment variables overriding system settings
  • PostgreSQL initialization parameters
  • Compile-time defaults

First, verify both PostgreSQL and system timezones:

-- PostgreSQL timezone check
SELECT current_setting('TIMEZONE') AS postgres_tz, 
       pg_postmaster_start_time() AS server_start_time;

-- System time check
\! date

The GMT default usually comes from:

1. initdb --lc-time=C during cluster creation
2. PGTZ environment variable
3. postgresql.conf containing timezone = 'GMT'
4. PostgreSQL compiled with --with-system-tzdata pointing to wrong location

Permanent fix via postgresql.conf:

# Add to postgresql.conf
timezone = 'Europe/Vienna'
log_timezone = 'Europe/Vienna'

Temporary session override:

SET TIME ZONE 'Europe/Vienna';
ALTER DATABASE mydb SET timezone TO 'Europe/Vienna';

After making changes:

-- Check active timezone
SHOW timezone;

-- Verify timestamp behavior
SELECT now(), 
       now() AT TIME ZONE 'Europe/Vienna' AS local_time,
       now() AT TIME ZONE 'UTC' AS utc_time;

When building applications:

// Python example with psycopg2
import psycopg2
from datetime import datetime

conn = psycopg2.connect(
    "dbname=mydb options='-c timezone=Europe/Vienna'"
)
cursor = conn.cursor()
cursor.execute("SELECT now()")
print(cursor.fetchone()[0].astimezone())

Check for interfering variables:

# As postgres OS user
env | grep -E 'TZ|PGTZ'

# Alternative method
sudo -u postgres psql -c "SHOW TIMEZONE;"

When PostgreSQL 9.2 shows GMT timezone despite your system being configured for Europe/Vienna, it's often due to one of these overlooked factors:

# Check PostgreSQL's runtime environment
sudo -u postgres env | grep TZ

# Alternative method using process information
cat /proc/$(pgrep -u postgres postmaster | head -1)/environ | tr '\\0' '\\n' | grep TZ

Systemd or init scripts may override timezone settings. Check service definitions:

# For systemd systems
systemctl show postgresql.service | grep Environment

# For init.d systems
grep -r "TZ" /etc/init.d/postgresql

The timezone resolution follows this priority order:

  1. Session-level SET TIMEZONE command
  2. postgresql.conf timezone parameter
  3. PGTZ environment variable
  4. System timezone (via /etc/localtime)
  5. Compiled-in default (often GMT)

Use these SQL commands to diagnose:

-- Check active timezone configuration
SELECT name, setting, source FROM pg_settings WHERE name LIKE '%timezone%';

-- View timezone conversion examples
SELECT 
    now() AS server_time,
    (now() AT TIME ZONE 'Europe/Vienna') AS vienna_time,
    (now() AT TIME ZONE 'GMT') AS gmt_time;

For different scenarios:

-- Option 1: Set in postgresql.conf
timezone = 'Europe/Vienna'

-- Option 2: Set default for all new connections
ALTER DATABASE mydb SET timezone TO 'Europe/Vienna';

-- Option 3: Set PGTZ in service configuration
# Add to /etc/systemd/system/postgresql.service.d/override.conf
[Service]
Environment="PGTZ=Europe/Vienna"

When you can't change server settings, handle conversion in queries:

-- Convert stored timestamps to local time
SELECT created_at AT TIME ZONE 'UTC' AT TIME ZONE 'Europe/Vienna' 
FROM events;

-- Insert with explicit timezone
INSERT INTO logs (event_time)
VALUES ('2023-01-01 12:00:00 Europe/Vienna'::timestamptz);