CodeGym /Kurslar /SQL SELF /Zaman zonaları ilə işləmək: TIMEZONE

Zaman zonaları ilə işləmək: TIMEZONE

SQL SELF
Səviyyə , Dərs
Mövcuddur

Təsəvvür elə, sənin aviabilet bronlama app-ın var. Reys Nyu-Yorkdan yerli vaxtla 10:00-da uçur və Londona yerli vaxtla 22:00-da çatır. Zaman zonalarını nəzərə almasan, serverin tam xaosa çevrilə bilər və yanlış eniş vaxtı göstərə bilər.

Zaman zonaları — sənin ən yaxın dostların (ya da hər şey tərsinə gedəndə ən pis düşmənin). Əgər istifadəçilərin müxtəlif ölkələrdədirsə və ya cədvəllərlə işləyirsənsə, hansı ki, yerli vaxta bağlıdır (məsələn, reys vaxtları və ya tədbir cədvəlləri), onda zaman zonalarını nəzərə almaq kritik dərəcədə vacib olur.

Zaman tipli verilənlər

Artıq danışmışdıq ki, zaman möhürləri ilə işləmək üçün iki data tipi var:

  • TIMESTAMP: tarix və vaxt zaman zonası nəzərə alınmadan.
  • TIMESTAMPTZ: tarix və vaxt zaman zonası ilə birlikdə.

Gəlin bunları bir də nümunə ilə baxaq.

-- İki sütunlu cədvəl yaradırıq: TIMESTAMP və TIMESTAMPTZ
CREATE TABLE flight_schedule (
    flight_id SERIAL PRIMARY KEY,
    departure_time TIMESTAMP,
    departure_time_with_tz TIMESTAMPTZ
);

-- Məlumat əlavə edirik
INSERT INTO flight_schedule (departure_time, departure_time_with_tz)
VALUES
    ('2023-10-25 10:00:00', '2023-10-25 10:00:00+00');

-- Məlumatı yoxlayaq
SELECT * FROM flight_schedule;

Nəticə serverinin zaman zonasından asılı olacaq. Məsələn:

flight_id departure_time departure_time_with_tz
1 2023-10-25 10:00:00 2023-10-25 10:00:00+00

Əsas fərq:

  • departure_time sütunu sadəcə tarix və vaxtı saxlayır, heç bir zaman zonasına bağlı deyil.
  • departure_time_with_tz sütunu isə tarix və vaxtı zaman zonası ilə birlikdə saxlayır (+00 bu nümunədə).

Zamanı fərqli zaman zonalarına çevirmək

PostgreSQL-də zaman zonaları ilə işləmək üçün AT TIME ZONE funksiyasından istifadə olunur.

UTC-ni lokal vaxta çevirmək

Tutaq ki, UTC formatında zaman möhürümüz var (beynəlxalq koordinasiyalı vaxt). Onu America/New_York zaman zonasındakı istifadəçiyə göstərmək istəyirik.

SELECT
    '2023-10-25 14:00:00+00'::TIMESTAMPTZ AT TIME ZONE 'America/New_York' AS local_time;

Nəticə:

local_time
2023-10-25 10:00:00

AT TIME ZONE burada sanki sehrli çubuq kimidir: vaxtı UTC-dən göstərilən zaman zonasına çevirir.

Lokal vaxtı UTC-yə çevirmək

İndi isə əks tapşırıq: America/New_York zaman zonasındakı vaxtı UTC-yə çevirmək istəyirik.

SELECT
    '2023-10-25 10:00:00'::TIMESTAMP AT TIME ZONE 'America/New_York' AS utc_time;

Nəticə:

utc_time
2023-10-25 14:00:00+00

Diqqət elə, nəticə TIMESTAMPTZ formatında olacaq, çünki zaman zonası (bu halda UTC) haqqında məlumatı da saxlayır.

TIMESTAMPTZ data tipi ilə işləmək

TIMESTAMPTZ ilə işləyəndə, PostgreSQL avtomatik olaraq serverinin (və ya sənin təyin etdiyin) zaman zonasını nəzərə alır.

Cari sessiya üçün zaman zonasını belə təyin edə bilərsən:

SET TIMEZONE = 'Europe/Istanbul';

Bundan sonra bütün TIMESTAMPTZ əməliyyatları bu zaman zonası ilə işləyəcək.

Nümunə: məlumat əlavə etmək və seçmək

-- Zaman zonasını təyin edirik
SET TIMEZONE = 'Europe/Istanbul';

-- Məlumat əlavə edirik
INSERT INTO flight_schedule (departure_time_with_tz)
VALUES ('2023-10-25 10:00:00+00');

-- Məlumatı yoxlayaq
SELECT departure_time_with_tz FROM flight_schedule;

Europe/Istanbul zaman zonasında nəticə:

departure_time_with_tz
2023-10-25 13:00:00+03

PostgreSQL vaxtı UTC-dən sənin göstərdiyin zaman zonasına avtomatik çevirir.

Praktiki nümunələr

Cədvəllər üçün zaman zonalarını nəzərə almaq. Tutaq ki, reys cədvəli olan bir cədvəlimiz var və hər qeyd UTC-də saxlanılır. Hər reys üçün çıxış vaxtını istifadəçinin lokal vaxtında göstərmək istəyirik.

SELECT
    flight_id,
    departure_time_with_tz AT TIME ZONE 'America/New_York' AS local_time
FROM flight_schedule;

Fərqli zaman zonalarından olan zaman məlumatlarını müqayisə etmək. Təsəvvür elə, iki hadisəni müqayisə edirik, biri bir şəhərdə, digəri başqa şəhərdə baş verib. PostgreSQL bunu avtomatik olaraq vahid zaman zonasına çevirib müqayisə etməyə imkan verir.

SELECT
    '2023-10-25 10:00:00+03'::TIMESTAMPTZ > '2023-10-25 07:00:00+00'::TIMESTAMPTZ AS event_one_later;

Nəticə:

event_one_later
t

Müqayisə true qaytardı, çünki 10:00+03 əslində 07:00+00-a bərabərdir.

Məsləhətlər və tez-tez rast gəlinən problemlər

Zamanla işləmək — hiyləgər işdir. Bax, tez-tez nə baş verir:

  • TIMESTAMP əvəzinə TIMESTAMPTZ istifadə etmirlər və sonra təəccüblənirlər ki, vaxt niyə düz gəlmir — çünki zaman zonaları sadəcə nəzərə alınmır.
  • Serverin hansı zaman zonasında işlədiyini bilmirlər və nəticədə məlumat bir vaxtda yazılır, başqa vaxtda oxunur.
  • AT TIME ZONE istifadə edəndə zaman zonasının adında səhv edirlər — və ya error alırlar, ya da səhv vaxt.

Belə problemlərə düşməmək üçün:

  • Demək olar ki, həmişə TIMESTAMPTZ istifadə et, xüsusən də məlumat zaman zonasından asılıdırsa.
  • Vaxtı həmişə UTC-də saxla, istifadəçiyə göstərərkən isə lazım olan zaman zonasına çevir.
  • Daha dərindən başa düşmək istəyirsənsə, bax PostgreSQL-in rəsmi vaxt və zaman zonası sənədi — çox faydalı şeydir.
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION