Hvis du faktisk har en kolonne af typen timestamp
og fortolke det (i dele) afhængigt af den aktuelle tidszone, og denne tidszone kan variere, så er et indeks generelt umuligt . Du kan kun bygge et indeks på IMMUTABLE
data ...
Efter opdatering:
For at besvare disse spørgsmål:
- Hvilke reservationer starter "i dag"?
- Hvilke reservationer har startdatoer i fremtiden?
- Hvilke reservationer har tidligere startdatoer?
... du bedst gemmer et timestamp with time zone
. Bare en date
er ikke præcis nok.
Så længe vi kun er interesserede i det lokale "i dag" (som defineret af den aktuelle tidszone ), gør vi ikke skal gemme tidszonen eksplicit. Vi er ligeglade med, hvor i verden det sker, vi har kun brug for et absolut tidspunkt at sammenligne med.
Så for at få reservationer fra "i dag" skal du blot:
SELECT *
FROM reservations
WHERE start_on::date = current_date;
Men dette er ikke sargerbart
fordi start_on::date
er et afledt udtryk, og vi kan heller ikke bygge et funktionelt indeks for dette (uden beskidte tricks), fordi udtrykket afhænger af den aktuelle tidszone og ikke er IMMUTABLE
.
I stedet , sammenlign med starten og slutningen af "vores" dag i UTC-tid:
SELECT *
FROM reservations
WHERE start_on >= current_date::timestamptz
AND start_on < (current_date + 1)::timestamptz; -- exclude upper border
Nu kan dette simple indeks understøtte forespørgslen:
CREATE INDEX ON reservations (start_on);
Demo
SQL Fiddle er nede i ATM. Her er en lille demo for at hjælpe med at forstå:
CREATE TEMP TABLE reservations (
reservation_id serial
, start_on timestamptz NOT NULL
, time_zone text); -- we don't need this
INSERT INTO reservations (start_on, time_zone) VALUES
('2014-04-09 01:00+02', 'Europe/Vienna')
, ('2014-04-09 23:00+02', 'Europe/Vienna')
, ('2014-04-09 01:00+00', 'UTC') -- the value is independent of the time zone
, ('2014-04-09 23:00+00', 'UTC') -- only display depends on current time zone
, ('2014-04-09 01:00-07', 'America/Los_Angeles')
, ('2014-04-09 23:00-07', 'America/Los_Angeles');
SELECT start_on, time_zone
, start_on::timestamp AS local_ts
, start_on AT TIME ZONE time_zone AS ts_at_tz
, current_date::timestamptz AS lower_bound
, (current_date + 1)::timestamptz AS upper_bound
FROM reservations
WHERE start_on >= current_date::timestamptz
AND start_on < (current_date + 1)::timestamptz;
Mere forklaring og links her:
Ignorerer tidszoner helt i Rails og PostgreSQL