2013-06-01 23 views
13

Kuveyt saat dilimindeki bir sistemden gelen veritabanı tablosumda bir UNIX zaman damgası sütunu var.Saat sunucusundan saat sunucusundaki saat dilimi ile sql sunucusundaki tarih saat dönüşümü

Veritabanı sunucumun saat dilimi Eastern Time US & Canada dur. Şimdi UNIX zaman damgasını bir SQL sorgusu kullanarak Kuveyt saat dilimi tarih değerine dönüştürmem gerekiyor.

Bu UNIX zaman damgasını Kuveyt saat dilimi tarih değerine nasıl dönüştürebileceğimi söyleyen var mı?

cevap

24

Unix zaman damgası 1 Ocak 1970'den beri tamsayıdır.

Veritabanınızda bu numaraya sahip bir tamsayı sütununuz olduğu anlamına gelirse, bu durumda veritabanı sunucunuzun saat dilimi alakasız olur.

İlk önce datetime tipine damgası dönüştürmek:

SELECT DATEADD(second, yourTimeStamp, '1970-01-01') 

Bu zaman damgası tekabül UTC datetime olacaktır.

Ardından, bu değeri hedef saat diliminize nasıl ayarlayacağınızı bilmeniz gerekir. Dünyanın çoğunda, Tek Bölge, Yaz Saati Uygulaması nedeniyle çoklu ofsetlere sahip olabilir.

Ne yazık ki, SQL Server'ın çalışma zamanı bölgelerini doğrudan çalışma yeteneği yoktur. Öyleyse, örneğin, ABD Pasifik zamanını kullanıyor olsaydınız, 7 saat ya da 8 saat çıkarmanız gerekip gerekmediğini bilmenin bir yolu olmazdı. Diğer veritabanları (Oracle, Postgres, MySql, vb) bunu işlemek için yerleşik bir yol var, ancak alas, SQL Server yok. Bir tabloya

  • İthalat saat dilimi verilerini ve saat dilimi kuralları değiştikçe bu tabloyu sürdürmek: Yani bir genel amaçlı çözüm arıyorsanız eğer, aşağıdakilerden birini yapmanız gerekir. Belirli bir tarihte ofseti çözmek için bu tabloyu bir grup özel mantıkla kullanın.

  • Saat dilimi verilerini içeren Windows kayıt defteri anahtarlarını almak için xp_regread kullanın ve belirli bir tarihte ofseti çözmek için yeniden bir dizi özel mantık kullanın. Tabii ki, xp_regread yapmak için kötü bir şey, verilen belirli izinler gerektirir ve desteklenmez veya belge.

  • .Net'de TimeZoneInfo sınıfını kullanan bir SQLCLR işlevi yazın. Ne yazık ki, bu requires an "unsafe" SQLCLR assembly ve kötü şeylerin olmasına neden olabilir.

IMHO, bu yaklaşımlardan hiçbiri çok iyi değildir ve bunu doğrudan SQL'de yapmak için iyi bir çözüm yoktur. En iyi çözüm, UTC değerini (orijinal tamsayı ya da datetime UTC'de) çağıran uygulama kodunuza döndürmek ve bunun yerine saat dilimi dönüşümünü yapmaktır (örneğin, TimeZoneInfo içinde .Net veya benzeri benzer mekanizmalarla) platformlar).

NASIL - Kuveyt’in (Günışığı Tasarrufu Zamanı için değişmeyen bir bölgede) olduğu (ve her zaman olduğu gibi) için çok şanslısınız. Her zaman UTC + 03: 00 olmuştur. Yani basitçe üç saat eklemek ve sonucu dönebilirsiniz:

SELECT DATEADD(hour, 3, DATEADD(second, yourTimeStamp, '1970-01-01')) 

Ama bu herhangi bir zaman diliminde çalışacak bir genel amaçlı çözüm olmadığını fark yoktur.

İsterseniz, datetimeoffset gibi diğer SQL veri türlerinden birini döndürebilirsiniz, ancak bu yalnızca değerin kime görünebileceğine dair üç saatlik bir değer olduğunu yansıtmanıza yardımcı olur. Dönüşüm işlemini farklı veya daha iyi yapmaz.


SQL Server zaman dilimlerini desteklemek için bir proje oluşturduk

Güncelleme Cevap. from here yükleyebilirsiniz. Sonra basitçe şöyle dönüştürebilirsiniz: Sen yaz saati kullanan olanlar dahil any time zone from the IANA tz database kullanabilirsiniz

SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'Asia/Kuwait') 

.

Bir unix zaman damgasından dönüştürmek için yukarıda gösterilen yöntemi kullanmaya devam edebilirsiniz. ikisi birlikte koyarak:

SELECT Tzdb.UtcToLocal(DATEADD(second, yourTimeStamp, '1970-01-01'), 'Asia/Kuwait') 

SQL Server 2016 ile kullanıcılar Yine

Güncelleme, şimdi orada yerleşik olan desteğin AT TIME ZONE ifadesiyle saat dilimleri için. Bu, Azure SQL Veritabanı'nda (v12) de bulunur.

SELECT DATEADD(second, yourTimeStamp, '1970-01-01') AT TIME ZONE 'Arab Standard Time' 

More examples in this announcement.

+0

bu sorguyu kullanmak ve bu benim için çalışıyor. SEÇ CAST (SWITCHOFFSET (CAST (dateadd (s, 1356052117, '01/01/1970') Datetimeoffset AS), '03: 00') DATETIME AS) –

+2

Eh, ofset anahtarlama GİBİ [Tarih] iyidir - Eğer uygulamanızda 'DateTimeOffset' ile çalışacaksanız. Ama eğer bir "datetime" a geri dönüyorsanız, o zaman gerçek bir ek avantaj yoktur. Sadece 3 saat ekleyebilirsin. –

+0

Ayrıca - Görüyorum ki 'tarih' için döküm yapıyoruz. Bu, herhangi bir zaman bileşenini keser. İstediğinizi yapmadıkça, bunun yerine “datetime” a gitmelisiniz. –