Selasa, 06 Agustus 2019

Teknik Menyimpan Tanggal dan Waktu di SQL Server

Untuk menyimpan tanggal dan waktu di SQL Server, gunakan GETUTCDATE() jangan menggunakan GETDATE() karena fungsi ini akan menghasilkan tanggal dan waktu komputer server (bukan waktu GMT/UTC dan bukan waktu komputer client)

Tipe kolom yang digunakan boleh DATETIME2(2) karena ukuran 6 bytes (kalau DATETIME ukurannya 8 bytes). Angka (2) artinya ketelitian 2 digit miliseconds. (baca referensi)

Untuk menampilkan tanggal dan waktu dalam zona waktu komputer client, maka digunakan fungsi <nama kolom> AT TIME ZONE <nama time zone> (baca referensi). Tipe data yang dihasilkan oleh fungsi ini adalah datetimeoffset (baca referensi)

Contoh penggunaan:


CREATE TABLE dbo.tbUser (
idData INT PRIMARY KEY,
namaTimeZone VARCHAR(50)
);
GO

CREATE TABLE dbo.tbTransaksi (
idData INT PRIMARY KEY,
idUser INT,
waktuInput DATETIME2(2) DEFAULT GETUTCDATE()
);
GO

INSERT INTO dbo.tbUser VALUES (1,'Pacific Standard Time'); --GMT-8
INSERT INTO dbo.tbUser VALUES (2,'SE Asia Standard Time'); --GMT+7
INSERT INTO dbo.tbTransaksi (idData,idUser) VALUES (1,1),(2,2); --WAKTU INPUT OTOMATIS GETUTCDATE()
GO

CREATE PROCEDURE dbo.prLaporan
AS
BEGIN
SELECT 
a.idData,a.idUser,
a.waktuInput AS [Waktu UTC], 
a.waktuInput AT TIME ZONE b.namaTimeZone AS [Waktu User], 
b.namaTimeZone AS [TimeZone] 
FROM dbo.tbTransaksi a LEFT JOIN dbo.tbUser b ON a.idUser=b.idData;
END
GO

EXEC dbo.prLaporan;
GO

--DROP PROCEDURE dbo.prLaporan;
--DROP TABLE dbo.tbTransaksi;
--DROP TABLE dbo.tbUser;

Hasil dari eksekusi prosedure dbo.prLaporan adalah seperti gambar dibawah.

Untuk mengkonversi waktu user sehingga yang tampil adalah waktu lokal (bukan waktu UTC + interval waktu), dapat digunakan source code berikut:
Versi T-SQL SQL Server:
SELECT GETUTCDATE();
SELECT GETUTCDATE() AT TIME ZONE 'SE Asia Standard Time';
SELECT DATEPART(tz, (SELECT GETUTCDATE() AT TIME ZONE 'SE Asia Standard Time'));
SELECT DATEADD(mi,DATEPART(tz, (SELECT GETUTCDATE() AT TIME ZONE 'SE Asia Standard Time')),GETUTCDATE());
Klik untuk baca referensi DATEPART dan DATEADD

Versi C# ASP.NET:
using (SqlConnection cn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["connString"].ConnectionString))
{
    using (SqlCommand cmd = new SqlCommand())
    {
        cmd.Connection = cn;
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = "dbo.prLaporan";
        cn.Open();
        using (SqlDataReader rea = cmd.ExecuteReader())
        {
            if (rea.HasRows)
            {
                lblInfo.Text = "";
                while (rea.Read())
                {
                    lblInfo.Text += $"ID Data = {rea["idData"]}<br />";
                    lblInfo.Text += $"ID User = {rea["idUser"]}<br />";
                    lblInfo.Text += $"Waktu UTC = {rea["Waktu UTC"]}<br />";
                    lblInfo.Text += $"Waktu User = {rea["Waktu User"]}<br />";
                    lblInfo.Text += $"TimeZone = {rea["TimeZone"]}<br />";
                    string lokal = DateTimeOffset.Parse(rea["Waktu User"].ToString()).DateTime.Add(DateTimeOffset.Parse(rea["Waktu User"].ToString()).Offset).ToString("yyyy-MM-dd HH:mm:ss");
                    lblInfo.Text += $"<b>Format Waktu User = {lokal}</b><br /><br />";
                }
            }
        }
        cn.Close();
    }
}

Sebagai tambahan, untuk mendapatkan daftar zona waktu, gunakan source code berikut:
Versi T-SQL SQL Server:
SELECT * FROM sys.time_zone_info;

Versi C# ASP.NET:
ReadOnlyCollection<TimeZoneInfo> tz = TimeZoneInfo.GetSystemTimeZones();
lblInfo.Text = "<table>";
lblInfo.Text += $"<tr><th>DisplayName</th><th>Id</th><th>BaseUtcOffset</th></tr>";
foreach (TimeZoneInfo tzInfo in tz)
{
    lblInfo.Text += $"<tr><td>{tzInfo.DisplayName}</td><td>{tzInfo.Id}</td><td>{tzInfo.BaseUtcOffset}</td></tr>";
}
lblInfo.Text += "</table>";

NB: Jika wilayah tsb sedang dalam DST, maka waktu akan dimajukan 1 jam dari zona waktu standard wilayah tersebut. (baca referensi)

Tidak ada komentar:

Posting Komentar