Share via


Mengonversi waktu antar zona waktu

Ini menjadi semakin penting bagi aplikasi apa pun yang bekerja dengan tanggal dan waktu untuk menangani perbedaan antara zona waktu. Aplikasi tidak dapat lagi mengasumsi bahwa semua waktu dapat diekspresikan dalam waktu lokal, yaitu waktu yang tersedia dari struktur DateTime. Misalnya, halaman web yang menampilkan waktu saat ini di bagian timur Amerika Serikat akan tidak memiliki kredibilitas kepada pelanggan di Asia timur. Artikel ini menjelaskan cara mengonversi waktu dari satu zona waktu ke zona waktu lainnya dan mengonversi DateTimeOffset nilai yang memiliki kesadaran zona waktu terbatas.

Mengonversi Waktu Universal Terkoordinasi

Waktu Universal Terkoordinasi (UTC) adalah standar waktu atomik presisi tinggi. Zona waktu dunia diekspresikan sebagai offset positif atau negatif dari UTC. Dengan demikian, UTC menyediakan waktu bebas zona waktu atau waktu netral zona waktu. Penggunaan UTC direkomendasikan ketika portabilitas tanggal dan waktu di seluruh komputer penting. Untuk detail dan praktik terbaik lainnya menggunakan tanggal dan waktu, lihat Praktik terbaik pengodean menggunakan DateTime di .NET Framework. Mengonversi zona waktu individual ke UTC memudahkan perbandingan waktu.

Catatan

Anda juga dapat menserialisasikan DateTimeOffset struktur untuk mewakili satu titik waktu secara tidak ambigu. Karena DateTimeOffset objek menyimpan nilai tanggal dan waktu bersama dengan offsetnya dari UTC, objek selalu mewakili titik waktu tertentu dalam kaitannya dengan UTC.

Cara termudah untuk mengonversi waktu ke UTC adalah dengan memanggil metode static (Shared dalam Visual Basic) TimeZoneInfo.ConvertTimeToUtc(DateTime). Konversi yang tepat yang dilakukan oleh metode tergantung pada nilai dateTime properti parameter Kind , seperti yang ditunjukkan oleh tabel berikut:

DateTime.Kind Konversi
DateTimeKind.Local Mengonversi waktu lokal ke UTC.
DateTimeKind.Unspecified Mengasumsikan parameter dateTime adalah waktu lokal dan mengonversi waktu lokal ke UTC.
DateTimeKind.Utc Mengembalikan parameter dateTime yang tidak berubah.

Kode berikut mengonversi waktu lokal saat ini ke UTC dan menampilkan hasilnya ke konsol:

DateTime dateNow = DateTime.Now;
Console.WriteLine($"The date and time are {TimeZoneInfo.ConvertTimeToUtc(dateNow)} UTC.");
Dim dateNow As Date = Date.Now
Console.WriteLine("The date and time are {0} UTC.", _
                  TimeZoneInfo.ConvertTimeToUtc(dateNow))

Jika nilai tanggal dan waktu tidak mewakili waktu lokal atau UTC, ToUniversalTime metode kemungkinan akan mengembalikan hasil yang salah. Namun, Anda dapat menggunakan metode TimeZoneInfo.ConvertTimeToUtc untuk mengonversi tanggal dan waktu dari zona waktu yang ditentukan. Untuk detail tentang mengambil TimeZoneInfo objek yang mewakili zona waktu tujuan, lihat Menemukan zona waktu yang ditentukan pada sistem lokal. Kode berikut menggunakan TimeZoneInfo.ConvertTimeToUtc metode untuk mengonversi Waktu Standar Timur ke UTC:

DateTime easternTime = new DateTime(2007, 01, 02, 12, 16, 00);
string easternZoneId = "Eastern Standard Time";
try
{
    TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId);
    Console.WriteLine($"The date and time are {TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone)} UTC.");
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine($"Unable to find the {easternZoneId} zone in the registry.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine($"Registry data on the {easternZoneId} zone has been corrupted.");
}
Dim easternTime As New Date(2007, 01, 02, 12, 16, 00)
Dim easternZoneId As String = "Eastern Standard Time"
Try
    Dim easternZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId)
    Console.WriteLine("The date and time are {0} UTC.", _
                      TimeZoneInfo.ConvertTimeToUtc(easternTime, easternZone))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("Unable to find the {0} zone in the registry.", _
                      easternZoneId)
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the {0} zone has been corrupted.", _
                      easternZoneId)
End Try

Metode ini TimeZoneInfo.ConvertTimeToUtc melemparkan ArgumentException jika DateTime properti objek Kind dan zona waktu tidak cocok. Ketidakcocokan terjadi jika Kind properti tetapi DateTimeKind.LocalTimeZoneInfo objek tidak mewakili zona waktu lokal, atau jika Kind properti adalah DateTimeKind.Utc tetapi TimeZoneInfo objek tidak sama dengan TimeZoneInfo.Utc.

Semua metode ini mengambil nilai DateTime sebagai parameter dan mengembalikan nilai DateTime. Untuk nilai DateTimeOffset, struktur DateTimeOffset memiliki metode instans ToUniversalTime yang mengonversi tanggal dan waktu instans saat ini ke UTC. Contoh berikut memanggil ToUniversalTime metode untuk mengonversi waktu lokal dan beberapa kali lagi ke UTC:

DateTimeOffset localTime, otherTime, universalTime;

// Define local time in local time zone
localTime = new DateTimeOffset(new DateTime(2007, 6, 15, 12, 0, 0));
Console.WriteLine("Local time: {0}", localTime);
Console.WriteLine();

// Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero);
Console.WriteLine("Other time: {0}", otherTime);
Console.WriteLine("{0} = {1}: {2}",
                  localTime, otherTime,
                  localTime.Equals(otherTime));
Console.WriteLine("{0} exactly equals {1}: {2}",
                  localTime, otherTime,
                  localTime.EqualsExact(otherTime));
Console.WriteLine();

// Convert other time to UTC
universalTime = localTime.ToUniversalTime();
Console.WriteLine("Universal time: {0}", universalTime);
Console.WriteLine("{0} = {1}: {2}",
                  otherTime, universalTime,
                  universalTime.Equals(otherTime));
Console.WriteLine("{0} exactly equals {1}: {2}",
                  otherTime, universalTime,
                  universalTime.EqualsExact(otherTime));
Console.WriteLine();
// The example produces the following output to the console:
//    Local time: 6/15/2007 12:00:00 PM -07:00
//
//    Other time: 6/15/2007 7:00:00 PM +00:00
//    6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True
//    6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False
//
//    Universal time: 6/15/2007 7:00:00 PM +00:00
//    6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True
//    6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True
Dim localTime, otherTime, universalTime As DateTimeOffset

' Define local time in local time zone
localTime = New DateTimeOffset(#6/15/2007 12:00:00PM#)
Console.WriteLine("Local time: {0}", localTime)
Console.WriteLine()

' Convert local time to offset 0 and assign to otherTime
otherTime = localTime.ToOffset(TimeSpan.Zero)
Console.WriteLine("Other time: {0}", otherTime)
Console.WriteLine("{0} = {1}: {2}", _
                  localTime, otherTime, _
                  localTime.Equals(otherTime))
Console.WriteLine("{0} exactly equals {1}: {2}", _
                  localTime, otherTime, _
                  localTime.EqualsExact(otherTime))
Console.WriteLine()

' Convert other time to UTC
universalTime = localTime.ToUniversalTime()
Console.WriteLine("Universal time: {0}", universalTime)
Console.WriteLine("{0} = {1}: {2}", _
                  otherTime, universalTime, _
                  universalTime.Equals(otherTime))
Console.WriteLine("{0} exactly equals {1}: {2}", _
                  otherTime, universalTime, _
                  universalTime.EqualsExact(otherTime))
Console.WriteLine()
' The example produces the following output to the console:
'    Local time: 6/15/2007 12:00:00 PM -07:00
'    
'    Other time: 6/15/2007 7:00:00 PM +00:00
'    6/15/2007 12:00:00 PM -07:00 = 6/15/2007 7:00:00 PM +00:00: True
'    6/15/2007 12:00:00 PM -07:00 exactly equals 6/15/2007 7:00:00 PM +00:00: False
'    
'    Universal time: 6/15/2007 7:00:00 PM +00:00
'    6/15/2007 7:00:00 PM +00:00 = 6/15/2007 7:00:00 PM +00:00: True
'    6/15/2007 7:00:00 PM +00:00 exactly equals 6/15/2007 7:00:00 PM +00:00: True   

Mengonversi UTC ke zona waktu yang ditentukan

Untuk mengonversi UTC ke waktu lokal, lihat bagian Mengonversi UTC ke waktu lokal berikut ini. Untuk mengonversi UTC ke waktu dalam zona waktu apa pun yang Anda tentukan, panggil metode ConvertTimeFromUtc. Metode tersebut memerlukan dua parameter:

  • UTC yang akan dikonversi. Ini harus berupa nilai DateTime yang properti Kind-nya diatur ke Unspecified atau Utc.

  • Zona waktu yang akan dikonversi ke UTC.

Kode berikut mengonversi UTC ke Waktu Standar Pusat:

DateTime timeUtc = DateTime.UtcNow;
try
{
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
    Console.WriteLine("The date and time are {0} {1}.",
                      cstTime,
                      cstZone.IsDaylightSavingTime(cstTime) ?
                              cstZone.DaylightName : cstZone.StandardName);
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine("The registry does not define the Central Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.");
}
Dim timeUtc As Date = Date.UtcNow
Try
    Dim cstZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
    Dim cstTime As Date = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone)
    Console.WriteLine("The date and time are {0} {1}.", _
                      cstTime, _
                      IIf(cstZone.IsDaylightSavingTime(cstTime), _
                          cstZone.DaylightName, cstZone.StandardName))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("The registry does not define the Central Standard Time zone.")
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the Central Standard Time zone has been corrupted.")
End Try

Mengonversi UTC ke waktu lokal

Untuk mengonversi UTC ke waktu lokal, panggil metode ToLocalTime dari objek DateTime yang waktunya ingin Anda konversi. Perilaku metode yang tepat tergantung pada nilai properti objek Kind , seperti yang ditunjukkan tabel berikut:

DateTime.Kind Konversi
DateTimeKind.Local Mengembalikan nilai DateTime yang tidak berubah.
DateTimeKind.Unspecified Mengasumsikan bahwa nilai DateTime adalah UTC dan mengonversi UTC ke waktu lokal.
DateTimeKind.Utc Mengonversi nilai DateTime ke waktu lokal.

Catatan

Metode TimeZone.ToLocalTime ini berperilaku sama persis dengan metode DateTime.ToLocalTime. Dibutuhkan satu parameter, yang merupakan nilai tanggal dan waktu, untuk dikonversi.

Anda juga dapat mengonversi waktu di zona waktu yang ditentukan untuk waktu lokal dengan menggunakan metode static (Shared dalam Visual Basic) TimeZoneInfo.ConvertTime. Topik ini dibahas di bagian berikutnya.

Mengonversi antara dua zona waktu mana pun

Anda dapat mengonversi antara dua zona waktu mana pun menggunakan dua metode static (Shared dalam Visual Basic) dari kelas TimeZoneInfo:

  • ConvertTime

    Parameter metode ini adalah nilai tanggal dan waktu untuk dikonversi, objek TimeZoneInfo yang mewakili zona waktu nilai tanggal dan waktu, dan objek TimeZoneInfo yang mewakili zona waktu untuk mengonversi nilai tanggal dan waktu.

  • ConvertTimeBySystemTimeZoneId

    Parameter metode ini adalah nilai tanggal dan waktu untuk dikonversi, pengidentifikasi zona waktu nilai tanggal dan waktu, dan pengidentifikasi zona waktu bagi nilai tanggal dan waktu untuk dikonversi.

Kedua metode mengharuskan konversi properti Kind nilai tanggal dan waktu dan objek TimeZoneInfo atau pengidentifikasi zona waktu yang mewakili zona waktunya yang saling sesuai. Jika tidak, ArgumentException akan muncul. Misalnya, jika Kind properti nilai tanggal dan waktu adalah DateTimeKind.Local, pengecualian akan dilemparkan jika TimeZoneInfo objek yang diteruskan sebagai parameter ke metode tidak sama dengan TimeZoneInfo.Local. Pengecualian juga dilemparkan jika pengidentifikasi yang diteruskan sebagai parameter ke metode tidak sama dengan TimeZoneInfo.Local.Id.

Contoh berikut menggunakan ConvertTime metode untuk mengonversi dari Waktu Standar Hawaii ke waktu lokal:

DateTime hwTime = new DateTime(2007, 02, 01, 08, 00, 00);
try
{
    TimeZoneInfo hwZone = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time");
    Console.WriteLine("{0} {1} is {2} local time.",
            hwTime,
            hwZone.IsDaylightSavingTime(hwTime) ? hwZone.DaylightName : hwZone.StandardName,
            TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local));
}
catch (TimeZoneNotFoundException)
{
    Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.");
}
catch (InvalidTimeZoneException)
{
    Console.WriteLine("Registry data on the Hawaiian Standard Time zone has been corrupted.");
}
Dim hwTime As Date = #2/01/2007 8:00:00 AM#
Try
    Dim hwZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Hawaiian Standard Time")
    Console.WriteLine("{0} {1} is {2} local time.", _
                      hwTime, _
                      IIf(hwZone.IsDaylightSavingTime(hwTime), hwZone.DaylightName, hwZone.StandardName), _
                      TimeZoneInfo.ConvertTime(hwTime, hwZone, TimeZoneInfo.Local))
Catch e As TimeZoneNotFoundException
    Console.WriteLine("The registry does not define the Hawaiian Standard Time zone.")
Catch e As InvalidTimeZoneException
    Console.WriteLine("Registry data on the Hawaiian Standard Time zone has been corrupted.")
End Try

Mengonversi nilai DateTimeOffset

Nilai tanggal dan waktu yang diwakili oleh DateTimeOffset objek tidak sepenuhnya sadar zona waktu karena objek dipisahkan dari zona waktunya pada saat objek dibuat. Namun, dalam banyak kasus, aplikasi hanya perlu mengonversi tanggal dan waktu berdasarkan dua offset yang berbeda dari UTC daripada tepat waktu di zona waktu tertentu. Untuk melakukan konversi ini, Anda dapat memanggil metode ToOffset instans saat ini. Parameter tunggal metode adalah offset dari nilai tanggal dan waktu baru yang akan dikembalikan metode.

Misalnya, jika tanggal dan waktu permintaan pengguna untuk halaman web diketahui dan diserialisasikan sebagai string dalam format MM/dd/yyyy hh:mm:ss zzzz, metode berikut ReturnTimeOnServer mengonversi nilai tanggal dan waktu ini ke tanggal dan waktu di server web:

public DateTimeOffset ReturnTimeOnServer(string clientString)
{
   string format = @"M/d/yyyy H:m:s zzz";
   TimeSpan serverOffset = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now);

   try
   {
      DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture);
      DateTimeOffset serverTime = clientTime.ToOffset(serverOffset);
      return serverTime;
   }
   catch (FormatException)
   {
      return DateTimeOffset.MinValue;
   }
}
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset
    Dim format As String = "M/d/yyyy H:m:s zzz"
    Dim serverOffset As TimeSpan = TimeZoneInfo.Local.GetUtcOffset(DateTimeOffset.Now)

    Try
        Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture)
        Dim serverTime As DateTimeOffset = clientTime.ToOffset(serverOffset)
        Return serverTime
    Catch e As FormatException
        Return DateTimeOffset.MinValue
    End Try
End Function

Jika metode melewati string "9/1/2007 5:32:07 -05:00," yang menunjukkan tanggal dan waktu di zona waktu lima jam lebih awal dari UTC, menampilkan "9/1/2007 3:32:07 AM -07:00" untuk server yang terletak di zona Waktu Standar Pasifik AS.

Kelas TimeZoneInfo juga menyertakan kelebihan beban metode TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) yang melakukan konversi zona waktu dengan nilai ToOffset(TimeSpan). Parameter metode DateTimeOffset adalah nilai dan referensi ke zona waktu yang waktunya akan dikonversi. Panggilan metode mengembalikan nilai DateTimeOffset. Misalnya, metode ReturnTimeOnServer dalam contoh sebelumnya dapat ditulis ulang sebagai berikut untuk memanggil metode ConvertTime(DateTimeOffset, TimeZoneInfo).

public DateTimeOffset ReturnTimeOnServer(string clientString)
{
   string format = @"M/d/yyyy H:m:s zzz";

   try
   {
      DateTimeOffset clientTime = DateTimeOffset.ParseExact(clientString, format,
                                  CultureInfo.InvariantCulture);
      DateTimeOffset serverTime = TimeZoneInfo.ConvertTime(clientTime,
                                  TimeZoneInfo.Local);
      return serverTime;
   }
   catch (FormatException)
   {
      return DateTimeOffset.MinValue;
   }
}
Public Function ReturnTimeOnServer(clientString As String) As DateTimeOffset
    Dim format As String = "M/d/yyyy H:m:s zzz"

    Try
        Dim clientTime As DateTimeOffset = DateTimeOffset.ParseExact(clientString, format, CultureInfo.InvariantCulture)
        Dim serverTime As DateTimeOffset = TimeZoneInfo.ConvertTime(clientTime, TimeZoneInfo.Local)
        Return serverTime
    Catch e As FormatException
        Return DateTimeOffset.MinValue
    End Try
End Function

Lihat juga