Share via


Cara: Menggunakan zona waktu dalam aritmetika tanggal dan waktu

Biasanya, ketika Anda melakukan aritmatika tanggal dan waktu menggunakan nilai DateTime atau DateTimeOffset, hasilnya tidak mencerminkan aturan penyesuaian zona waktu apa pun. Ini berlaku bahkan ketika zona waktu nilai tanggal dan waktu dapat diidentifikasi dengan jelas (misalnya, ketika properti Kind diatur ke Local). Topik ini menunjukkan cara melakukan operasi aritmatika pada nilai tanggal dan waktu yang termasuk dalam zona waktu tertentu. Hasil operasi aritmatika akan mencerminkan aturan penyesuaian zona waktu.

Untuk menerapkan aturan penyesuaian ke aritmatika tanggal dan waktu

  1. Terapkan beberapa metode untuk menggabungkan nilai tanggal dan waktu dengan zona waktu tempatnya. Misalnya, nyatakan struktur yang menyertakan nilai tanggal dan waktu serta zona waktunya. Contoh berikut menggunakan pendekatan ini untuk menautkan nilai DateTime dengan zona waktunya.

    // Define a structure for DateTime values for internal use only
    internal struct TimeWithTimeZone
    {
       TimeZoneInfo TimeZone;
       DateTime Time;
    }
    
    ' Define a structure for DateTime values for internal use only
    Friend Structure TimeWithTimeZone
        Dim TimeZone As TimeZoneInfo
        Dim Time As Date
    End Structure
    
  2. Konversikan waktu menjadi Waktu Universal Terkoordinasi (UTC) dengan memanggil metode ConvertTimeToUtc atau metode ConvertTime.

  3. Lakukan operasi aritmatika pada waktu UTC.

  4. Konversikan waktu dari UTC ke zona waktu terkait waktu asli dengan memanggil metode TimeZoneInfo.ConvertTime(DateTime, TimeZoneInfo).

Contoh

Contoh berikut menambahkan dua jam dan tiga puluh menit ke 9 Maret 2008, pada pukul 01.30 Waktu Standar Pusat. Transisi zona waktu ke waktu musim panas terjadi tiga puluh menit kemudian, pada pukul 02.00 pada tanggal 9 Maret 2008. Karena contoh mengikuti empat langkah yang tercantum di bagian sebelumnya, contoh tersebut melaporkan waktu yang dihasilkan dengan benar sebagai 05.00 pada 9 Maret 2008.

using System;

public struct TimeZoneTime
{
   public TimeZoneInfo TimeZone;
   public DateTime Time;

   public TimeZoneTime(TimeZoneInfo tz, DateTime time)
   {
      if (tz == null)
         throw new ArgumentNullException("The time zone cannot be a null reference.");

      this.TimeZone = tz;
      this.Time = time;
   }

   public TimeZoneTime AddTime(TimeSpan interval)
   {
      // Convert time to UTC
      DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(this.Time, this.TimeZone);
      // Add time interval to time
      utcTime = utcTime.Add(interval);
      // Convert time back to time in time zone
      return new TimeZoneTime(this.TimeZone, TimeZoneInfo.ConvertTime(utcTime,
                              TimeZoneInfo.Utc, this.TimeZone));
   }
}

public class TimeArithmetic
{
   public const string tzName = "Central Standard Time";

   public static void Main()
   {
      try
      {
         TimeZoneTime cstTime1, cstTime2;

         TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById(tzName);
         DateTime time1 = new DateTime(2008, 3, 9, 1, 30, 0);
         TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

         cstTime1 = new TimeZoneTime(cst, time1);
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours);
         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time,
                                                    twoAndAHalfHours.ToString(),
                                                    cstTime2.Time);
      }
      catch
      {
         Console.WriteLine("Unable to find {0}.", tzName);
      }
   }
}
Public Structure TimeZoneTime
    Public TimeZone As TimeZoneInfo
    Public Time As Date

    Public Sub New(tz As TimeZoneInfo, time As Date)
        If tz Is Nothing Then _
           Throw New ArgumentNullException("The time zone cannot be a null reference.")

        Me.TimeZone = tz
        Me.Time = time
    End Sub

    Public Function AddTime(interval As TimeSpan) As TimeZoneTime
        ' Convert time to UTC
        Dim utcTime As DateTime = TimeZoneInfo.ConvertTimeToUtc(Me.Time, _
                                                                Me.TimeZone)
        ' Add time interval to time
        utcTime = utcTime.Add(interval)
        ' Convert time back to time in time zone
        Return New TimeZoneTime(Me.TimeZone, TimeZoneInfo.ConvertTime(utcTime, _
                                TimeZoneInfo.Utc, Me.TimeZone))
    End Function
End Structure

Module TimeArithmetic
    Public Const tzName As String = "Central Standard Time"

    Public Sub Main()
        Try
            Dim cstTime1, cstTime2 As TimeZoneTime

            Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tzName)
            Dim time1 As Date = #03/09/2008 1:30AM#
            Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

            cstTime1 = New TimeZoneTime(cst, time1)
            cstTime2 = cstTime1.AddTime(twoAndAHalfHours)

            Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, _
                                                       twoAndAHalfHours.ToString(), _
                                                       cstTime2.Time)
        Catch
            Console.WriteLine("Unable to find {0}.", tzName)
        End Try
    End Sub
End Module

Nilai DateTime dan DateTimeOffset dipisahkan dari zona waktu mana pun tempat nilai tersebut mungkin berada. Untuk melakukan aritmatika tanggal dan waktu dengan cara yang secara otomatis menerapkan aturan penyesuaian zona waktu, zona waktu tempat nilai tanggal dan waktu berada harus segera diidentifikasi. Ini berarti bahwa tanggal dan waktu dan zona waktu terkait harus digabungkan dengan erat. Ada beberapa cara untuk melakukan ini, yang mencakup hal-hal berikut:

  • Asumsikan bahwa semua waktu yang digunakan dalam aplikasi termasuk dalam zona waktu tertentu. Meskipun sesuai dalam beberapa kasus, pendekatan ini menawarkan fleksibilitas terbatas dan mungkin portabilitas terbatas.

  • Tentukan jenis yang menggabungkan tanggal dan waktu dengan erat dengan zona waktu terkait dengan menyertakan keduanya sebagai bidang jenis. Pendekatan ini digunakan dalam contoh kode, yang menentukan struktur untuk menyimpan tanggal dan waktu dan zona waktu di dua bidang anggota.

Contoh ini menggambarkan cara melakukan operasi aritmatika pada nilai DateTime sehingga aturan penyesuaian zona waktu diterapkan pada hasilnya. Namun, nilai DateTimeOffset dapat digunakan dengan mudah. Contoh berikut menggambarkan bagaimana kode dalam contoh asli mungkin disesuaikan untuk menggunakan DateTimeOffset, dan bukan nilai DateTime.

using System;

public struct TimeZoneTime
{
   public TimeZoneInfo TimeZone;
   public DateTimeOffset Time;

   public TimeZoneTime(TimeZoneInfo tz, DateTimeOffset time)
   {
      if (tz == null)
         throw new ArgumentNullException("The time zone cannot be a null reference.");

      this.TimeZone = tz;
      this.Time = time;
   }

   public TimeZoneTime AddTime(TimeSpan interval)
   {
      // Convert time to UTC
      DateTimeOffset utcTime = TimeZoneInfo.ConvertTime(this.Time, TimeZoneInfo.Utc);
      // Add time interval to time
      utcTime = utcTime.Add(interval);
      // Convert time back to time in time zone
      return new TimeZoneTime(this.TimeZone, TimeZoneInfo.ConvertTime(utcTime, this.TimeZone));
   }
}

public class TimeArithmetic
{
   public const string tzName = "Central Standard Time";

   public static void Main()
   {
      try
      {
         TimeZoneTime cstTime1, cstTime2;

         TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById(tzName);
         DateTime time1 = new DateTime(2008, 3, 9, 1, 30, 0);
         TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

         cstTime1 = new TimeZoneTime(cst,
                        new DateTimeOffset(time1, cst.GetUtcOffset(time1)));
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours);
         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time,
                                                    twoAndAHalfHours.ToString(),
                                                    cstTime2.Time);
      }
      catch
      {
         Console.WriteLine("Unable to find {0}.", tzName);
      }
   }
}
Public Structure TimeZoneTime
    Public TimeZone As TimeZoneInfo
    Public Time As DateTimeOffset

    Public Sub New(tz As TimeZoneInfo, time As DateTimeOffset)
        If tz Is Nothing Then _
           Throw New ArgumentNullException("The time zone cannot be a null reference.")

        Me.TimeZone = tz
        Me.Time = time
    End Sub

    Public Function AddTime(interval As TimeSpan) As TimeZoneTime
        ' Convert time to UTC
        Dim utcTime As DateTimeOffset = TimeZoneInfo.ConvertTime(Me.Time, TimeZoneInfo.Utc)
        ' Add time interval to time
        utcTime = utcTime.Add(interval)
        ' Convert time back to time in time zone
        Return New TimeZoneTime(Me.TimeZone, TimeZoneInfo.ConvertTime(utcTime, Me.TimeZone))
    End Function
End Structure

Module TimeArithmetic
    Public Const tzName As String = "Central Standard Time"

    Public Sub Main()
        Try
            Dim cstTime1, cstTime2 As TimeZoneTime

            Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tzName)
            Dim time1 As Date = #03/09/2008 1:30AM#
            Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

            cstTime1 = New TimeZoneTime(cst, _
                           New DateTimeOffset(time1, cst.GetUtcOffset(time1)))
            cstTime2 = cstTime1.AddTime(twoAndAHalfHours)

            Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, _
                                                       twoAndAHalfHours.ToString(), _
                                                       cstTime2.Time)
        Catch
            Console.WriteLine("Unable to find {0}.", tzName)
        End Try
    End Sub
End Module

Perhatikan bahwa jika penambahan ini hanya dilakukan pada nilai DateTimeOffset tanpa terlebih dahulu mengonversinya ke UTC, hasilnya mencerminkan titik waktu yang benar tetapi offset-nya tidak mencerminkan zona waktu yang ditentukan untuk waktu itu.

Mengompilasi kode

Contoh ini membutuhkan:

  • Bahwa namespace layanan System diimpor dengan pernyataan using (diperlukan dalam kode C#).

Lihat juga