返回介绍

如何:往返日期和时间值

发布于 2025-02-23 23:15:40 字数 12712 浏览 0 评论 0 收藏 0

在许多应用程序中,日期和时间值旨在明确标识单个时间点。 本主题说明如何保存和还原 DateTime 值, DateTimeOffset 值,以及使用时间的日期和时间值分区信息,以使已还原的值标识的已保存的值在同一时间。

往返 DateTime 值

  1. 将转换 DateTime 为通过调用其字符串表示形式的值 DateTime.ToString(String) 方法使用"o"格式说明符。
  2. 保存的字符串表示形式 DateTime 值到文件,或将其传递跨进程、 应用程序域或计算机边界。
  3. 检索表示的字符串 DateTime 值。
  4. 调用 DateTime.Parse(String, IFormatProvider, DateTimeStyles) 方法,并传入 DateTimeStyles.RoundtripKind 的值作为 styles 参数。

下面的示例演示如何保存/还原 DateTime 值。

const string fileName = @".\DateFile.txt";

StreamWriter outFile = new StreamWriter(fileName);

// Save DateTime value.
DateTime dateToSave = DateTime.SpecifyKind(new DateTime(2008, 6, 12, 18, 45, 15), 
                       DateTimeKind.Local);
string dateString = dateToSave.ToString("o");    
Console.WriteLine("Converted {0} ({1}) to {2}.", 
          dateToSave.ToString(), 
          dateToSave.Kind.ToString(), 
          dateString);    
outFile.WriteLine(dateString);
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName);
outFile.Close();
    
// Restore DateTime value.
DateTime restoredDate;
    
StreamReader inFile = new StreamReader(fileName);
dateString = inFile.ReadLine();
inFile.Close();
restoredDate = DateTime.Parse(dateString, null, DateTimeStyles.RoundtripKind);
Console.WriteLine("Read {0} ({2}) from {1}.", restoredDate.ToString(), 
                        fileName, 
                        restoredDate.Kind.ToString());
// The example displays the following output:
//  Converted 6/12/2008 6:45:15 PM (Local) to 2008-06-12T18:45:15.0000000-05:00.
//  Wrote 2008-06-12T18:45:15.0000000-05:00 to .\DateFile.txt.
//  Read 6/12/2008 6:45:15 PM (Local) from .\DateFile.txt.
Const fileName As String = ".\DateFile.txt"

Dim outFile As New StreamWriter(fileName)

' Save DateTime value.
Dim dateToSave As Date = DateTime.SpecifyKind(#06/12/2008 6:45:15 PM#, _
                        DateTimeKind.Local)
Dim dateString As String = dateToSave.ToString("o")    
Console.WriteLine("Converted {0} ({1}) to {2}.", dateToSave.ToString(), _
          dateToSave.Kind.ToString(), dateString)    
outFile.WriteLine(dateString)
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName)
outFile.Close()   
    
' Restore DateTime value.
Dim restoredDate As Date
    
Dim inFile As New StreamReader(fileName)
dateString = inFile.ReadLine()
inFile.Close()
restoredDate = DateTime.Parse(dateString, Nothing, DateTimeStyles.RoundTripKind)
Console.WriteLine("Read {0} ({2}) from {1}.", restoredDate.ToString(), _
          fileName, restoredDAte.Kind.ToString())
' The example displays the following output:
'  Converted 6/12/2008 6:45:15 PM (Local) to 2008-06-12T18:45:15.0000000-05:00.
'  Wrote 2008-06-12T18:45:15.0000000-05:00 to .\DateFile.txt.
'  Read 6/12/2008 6:45:15 PM (Local) from .\DateFile.txt.

当往返 DateTime 值,此方法成功保留所有本地和通用时间的时间。 例如,如果本地 DateTime 值保存在美国的系统上太平洋标准时区的系统会,并在位于美国中部标准时区的系统上还原,则还原的日期和时间会比原始时间晚两个小时,这反映了两个时区之间的时差。 但是,此方法对于未指定时间不一定准确。 所有 DateTime 值其 Kind 属性是 Unspecified 看做就好像它们是本地时间。 如果这不是这种情况, DateTime 将不会成功标识正确的点的时间。 针对此限制的解决方法是将日期和时间值与其时区紧密耦合,以便进行保存和还原操作。

往返 DateTimeOffset 值

  1. 将转换 DateTimeOffset 为通过调用其字符串表示形式的值 DateTimeOffset.ToString(String) 方法使用"o"格式说明符。
  2. 保存的字符串表示形式 DateTimeOffset 值到文件,或将其传递跨进程、 应用程序域或计算机边界。
  3. 检索表示的字符串 DateTimeOffset 值。
  4. 调用 DateTimeOffset.Parse(String, IFormatProvider, DateTimeStyles) 方法,并传入 DateTimeStyles.RoundtripKind 的值作为 styles 参数。

下面的示例演示如何保存/还原 DateTimeOffset 值。

const string fileName = @".\DateOff.txt";

StreamWriter outFile = new StreamWriter(fileName);

// Save DateTime value.
DateTimeOffset dateToSave = new DateTimeOffset(2008, 6, 12, 18, 45, 15, 
                         new TimeSpan(7, 0, 0));
string dateString = dateToSave.ToString("o");    
Console.WriteLine("Converted {0} to {1}.", dateToSave.ToString(), 
          dateString);    
outFile.WriteLine(dateString);
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName);
outFile.Close();
    
// Restore DateTime value.
DateTimeOffset restoredDateOff;
    
StreamReader inFile = new StreamReader(fileName);
dateString = inFile.ReadLine();
inFile.Close();
restoredDateOff = DateTimeOffset.Parse(dateString, null, 
                     DateTimeStyles.RoundtripKind);
Console.WriteLine("Read {0} from {1}.", restoredDateOff.ToString(), 
          fileName);
// The example displays the following output:
//  Converted 6/12/2008 6:45:15 PM +07:00 to 2008-06-12T18:45:15.0000000+07:00.
//  Wrote 2008-06-12T18:45:15.0000000+07:00 to .\DateOff.txt.
//  Read 6/12/2008 6:45:15 PM +07:00 from .\DateOff.txt.
Const fileName As String = ".\DateOff.txt"

Dim outFile As New StreamWriter(fileName)

' Save DateTime value.
Dim dateToSave As New DateTimeOffset(2008, 6, 12, 18, 45, 15, _
                   New TimeSpan(7, 0, 0))
Dim dateString As String = dateToSave.ToString("o")    
Console.WriteLine("Converted {0} to {1}.", dateToSave.ToString(), dateString)    
outFile.WriteLine(dateString)
Console.WriteLine("Wrote {0} to {1}.", dateString, fileName)
outFile.Close()   
    
' Restore DateTime value.
Dim restoredDateOff As DateTimeOffset
    
Dim inFile As New StreamReader(fileName)
dateString = inFile.ReadLine()
inFile.Close()
restoredDateOff = DateTimeOffset.Parse(dateString, Nothing, DateTimeStyles.RoundTripKind)
Console.WriteLine("Read {0} from {1}.", restoredDateOff.ToString(), fileName)
' The example displays the following output:
'  Converted 6/12/2008 6:45:15 PM +07:00 to 2008-06-12T18:45:15.0000000+07:00.
'  Wrote 2008-06-12T18:45:15.0000000+07:00 to .\DateOff.txt.
'  Read 6/12/2008 6:45:15 PM +07:00 from .\DateOff.txt.

此方法始终明确地标识 DateTimeOffset 作为时间中的单个点的值。 值然后可转换为协调世界时 (UTC) 通过调用 DateTimeOffset.ToUniversalTime 方法,或者它可以转换为特定时区中的时间通过调用 DateTimeOffset.ToOffset 或 TimeZoneInfo.ConvertTime(DateTimeOffset, TimeZoneInfo) 方法。 此方法的主要限制是该日期和时间算法,对执行时 DateTimeOffset 值,该值表示的时间以特定时区,可能不会产生准确的结果,对应于该时区。 这是因为当 DateTimeOffset 实例化值时,它从其时区解除关联。 因此,执行日期和时间计算时,无法再应用该时区的调整规则。 可以通过定义包含日期和时间值以及其随附时区的自定义类型,来解决此问题。

往返日期和时间值与其时区

  1. 定义一个类或具有两个字段的结构。 第一个字段是 DateTime 或 DateTimeOffset 对象和第二个都 TimeZoneInfo 对象。 下面的示例是这种类型的简单版本。
    [Serializable] public class DateInTimeZone
    {
       private TimeZoneInfo tz;
       private DateTimeOffset thisDate;
       
       public DateInTimeZone() {}
    
       public DateInTimeZone(DateTimeOffset date, TimeZoneInfo timeZone)
       {
        if (timeZone == null) 
         throw new ArgumentNullException("The time zone cannot be null.");
    
        this.thisDate = date;
        this.tz = timeZone;
       }
       
       public DateTimeOffset DateAndTime
       {
        get { 
         return this.thisDate;
        }
        set {
         if (value.Offset != this.tz.GetUtcOffset(value)) 
          this.thisDate = TimeZoneInfo.ConvertTime(value, tz);
         else
          this.thisDate = value;
        }
       }
       
       public TimeZoneInfo TimeZone
       {
        get {
         return this.tz;
        }
       }
    }
    
    <Serializable> Public Class DateInTimeZone
       Private tz As TimeZoneInfo
       Private thisDate As DateTimeOffset
    
       Public Sub New()
       End Sub
        
       Public Sub New(date1 As DateTimeOffset, timeZone As TimeZoneInfo)
        If timeZone Is Nothing Then 
         Throw New ArgumentNullException("The time zone cannot be null.")
        End If
        Me.thisDate = date1
        Me.tz = timeZone
       End Sub
       
       Public Property DateAndTime As DateTimeOffset
        Get
         Return Me.thisDate
        End Get
        Set
         If Value.Offset <> Me.tz.GetUtcOffset(Value) Then
          Me.thisDate = TimeZoneInfo.ConvertTime(Value, tz)
         Else
          Me.thisDate = Value
         End If
        End Set
       End Property
       
       Public ReadOnly Property TimeZone As TimeZoneInfo
        Get
         Return tz
        End Get
       End Property
    End Class
    
  2. 将与类标记 SerializableAttribute 属性。
  3. 序列化对象使用 BinaryFormatter.Serialize 方法。
  4. 对象使用还原 Deserialize 方法。
  5. 强制转换 (在 C# 中) 或者 (在 Visual Basic 中) 反序列化将对象转换为适当类型的对象。

下面的示例演示如何保存/还原对象存储日期和时间和时区信息。

const string fileName = @".\DateWithTz.dat";

DateTime tempDate = new DateTime(2008, 9, 3, 19, 0, 0);
TimeZoneInfo tempTz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateInTimeZone dateWithTz = new DateInTimeZone(new DateTimeOffset(tempDate, 
                tempTz.GetUtcOffset(tempDate)), 
                tempTz);
                
// Store DateInTimeZone value to a file
FileStream outFile = new FileStream(fileName, FileMode.Create);
try
{
   BinaryFormatter formatter = new BinaryFormatter();
   formatter.Serialize(outFile, dateWithTz);
   Console.WriteLine("Saving {0} {1} to {2}", dateWithTz.DateAndTime, 
           dateWithTz.TimeZone.IsDaylightSavingTime(dateWithTz.DateAndTime) ? 
           dateWithTz.TimeZone.DaylightName : dateWithTz.TimeZone.DaylightName, 
           fileName);
}
catch (SerializationException)
{
   Console.WriteLine("Unable to serialize time data to {0}.", fileName);
}
finally
{     
   outFile.Close();
}

// Retrieve DateInTimeZone value
if (File.Exists(fileName))
{
   FileStream inFile = new FileStream(fileName, FileMode.Open);
   DateInTimeZone dateWithTz2 = new DateInTimeZone();
   try
   {
    BinaryFormatter formatter = new BinaryFormatter();
    dateWithTz2 = formatter.Deserialize(inFile) as DateInTimeZone;   
    Console.WriteLine("Restored {0} {1} from {2}", dateWithTz2.DateAndTime, 
            dateWithTz2.TimeZone.IsDaylightSavingTime(dateWithTz2.DateAndTime) ? 
            dateWithTz2.TimeZone.DaylightName : dateWithTz2.TimeZone.DaylightName, 
            fileName);
   }
   catch (SerializationException)
   {
    Console.WriteLine("Unable to retrieve date and time information from {0}", 
            fileName);
   }
   finally
   {
    inFile.Close();
   }
}
// This example displays the following output to the console:
//  Saving 9/3/2008 7:00:00 PM -05:00 Central Daylight Time to .\DateWithTz.dat
//  Restored 9/3/2008 7:00:00 PM -05:00 Central Daylight Time from .\DateWithTz.dat    
Const fileName As String = ".\DateWithTz.dat"

Dim tempDate As Date = #9/3/2008 7:00:00 PM#
Dim tempTz As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
Dim dateWithTz As New DateInTimeZone(New DateTimeOffset(tempDate, _
                     tempTz.GetUtcOffset(tempDate)), _
                   tempTz)

' Store DateInTimeZone value to a file
Dim outFile As New FileStream(fileName, FileMode.Create)
Try
   Dim formatter As New BinaryFormatter()
   formatter.Serialize(outFile, dateWithTz)
   Console.WriteLine("Saving {0} {1} to {2}", dateWithTz.DateAndTime, _
       IIf(dateWithTz.TimeZone.IsDaylightSavingTime(dateWithTz.DateAndTime), _
         dateWithTz.TimeZone.DaylightName, dateWithTz.TimeZone.DaylightName), _
       fileName)
Catch e As SerializationException
   Console.WriteLine("Unable to serialize time data to {0}.", fileName)
Finally   
   outFile.Close()
End Try
      
' Retrieve DateInTimeZone value
If File.Exists(fileName) Then
   Dim inFile As New FileStream(fileName, FileMode.Open)
   Dim dateWithTz2 As New DateInTimeZone()
   Try
    Dim formatter As New BinaryFormatter()
    dateWithTz2 = DirectCast(formatter.Deserialize(inFile), DateInTimeZone)     
    Console.WriteLine("Restored {0} {1} from {2}", dateWithTz2.DateAndTime, _
            IIf(dateWithTz2.TimeZone.IsDaylightSavingTime(dateWithTz2.DateAndTime), _
            dateWithTz2.TimeZone.DaylightName, dateWithTz2.TimeZone.DaylightName), _
            fileName)
   Catch e As SerializationException
    Console.WriteLine("Unable to retrieve date and time information from {0}", _
            fileName)
   Finally      
    inFile.Close
   End Try
End If
' This example displays the following output to the console:
'  Saving 9/3/2008 7:00:00 PM -05:00 Central Daylight Time to .\DateWithTz.dat
'  Restored 9/3/2008 7:00:00 PM -05:00 Central Daylight Time from .\DateWithTz.dat    

此方法应始终明确地反映正确的二者之前和之后保存并还原,提供的组合的日期和时间和时区对象的实现不允许日期值变得与不同步的时间点时区值。

编译代码

这些示例需要:

  • 使用 C# 要导入以下命名空间的 using 语句或 Visual Basic Imports 语句:
    • System (仅限 C#)。
    • System.Globalization 。
    • System.IO 。
    • System.Runtime.Serialization 。
    • System.Runtime.Serialization.Formatters.Binary 。
  • 对 System.Core.dll 的引用。
  • 每个代码示例,除 DateInTimeZone 类,应包括在类或 Visual Basic 模块,包装在方法中,并从调用 Main 方法。

另请参阅

执行格式设置操作
在 DateTime、DateTimeOffset、TimeSpan 和 TimeZoneInfo 之间进行选择
Standard Date and Time Format Strings

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文