2012-05-29 7 views
23

Я конвертирую дату C# в строку. Позже, когда я конвертирую его обратно в объект DateTime, кажется, что они не равны.конвертировать C# дату времени в строку и обратно

const string FMT = "yyyy-MM-dd HH:mm:ss.fff"; 
DateTime now1 = DateTime.Now; 
string strDate = now1.ToString(FMT); 
DateTime now2 = DateTime.ParseExact(strDate, FMT, CultureInfo.InvariantCulture); 
Console.WriteLine(now1.ToBinary()); 
Console.WriteLine(now2.ToBinary()); 

Вот пример. Похоже, что все включено в строковый формат, когда я печатаю дату, оба отображаются одинаково, но когда я сравниваю объекты или дату печати в двоичном формате, я вижу разницу. Мне кажется странным, не могли бы вы объяснить, что здесь происходит?

Вот вывод для приведенного выше кода.

-8588633131198276118 
634739049656490000 
+0

Маленькая точка: если вы собираетесь разбирать строку с помощью 'InvariantCulture', то вы, вероятно, захотите передать' InvariantCulture' в метод ToString, просто для того, чтобы быть в безопасности: 'now1.ToString (FMT, CultureInfo. InvariantCulture); ' –

ответ

35

Вы должны использовать roundtrip format specifier "O" or "o" если вы хотите сохранить значение DateTime.

Спецификатор стандартного формата «O» или «o» представляет собой пользовательскую строку формата даты и времени с использованием шаблона, который сохраняет информацию о часовом поясе. Для значений DateTime этот спецификатор формата предназначен для сохранения значений даты и времени вместе с свойством DateTime.Kind в тексте. Отформатированную строку можно проанализировать с помощью метода DateTime.Parse (String, IFormatProvider, DateTimeStyles) или DateTime.ParseExact, если для параметра styles установлено значение DateTimeStyles.RoundtripKind.

Использование кода (кроме изменения строки формата):

const string FMT = "O"; 
DateTime now1 = DateTime.Now; 
string strDate = now1.ToString(FMT); 
DateTime now2 = DateTime.ParseExact(strDate, FMT, CultureInfo.InvariantCulture); 
Console.WriteLine(now1.ToBinary()); 
Console.WriteLine(now2.ToBinary()); 

я получаю:

-8588633127598789320 
-8588633127598789320 
+0

Спасибо. Это помогает :) – axe

+1

У меня была проблема с датами UTC с помощью этого метода. Ниже описано, как я его исправил. –

1

2 вещи:

  1. Вы можете использовать ParseExact перегрузка, которая принимает параметр DateTimeStyle, чтобы указать AssumeLocal.

  2. Там еще будет небольшая разница между now1 и now2, если не увеличить точность до 7 цифр вместо 3: «гггг-мм-дд чч: мм: ss.fffffff»

    const string FMT = "yyyy-MM-dd HH:mm:ss.fffffff"; 
        DateTime now1 = DateTime.Now; 
        string strDate = now1.ToString(FMT); 
        DateTime now2 = DateTime.ParseExact(strDate, FMT, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal); 
        Console.WriteLine(now1.ToBinary()); 
        Console.WriteLine(now2.ToBinary()); 
    

Даже без вышеуказанных изменений расчетная разница между now1 и now2 кажется небольшой, хотя двоичные значения не выглядят одинаковыми.

 TimeSpan difference = now2.Subtract(now1); 
     Console.WriteLine(difference.ToString()); 
+0

Спасибо. Мне нужно получить точно такое же значение, любая разница приведет к сбою в модульном тестировании, поэтому лучше использовать «O». – axe

-2

Просто используйте этот код этого времени преобразования даты в строку и строку на сегодняшний день время

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 

namespace DateTimeConvert 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
       label1.Text = ConvDate_as_str(textBox1.Text); 
     } 

     public string ConvDate_as_str(string dateFormat) 
     { 
      try 
      { 
       char[] ch = dateFormat.ToCharArray(); 
       string[] sps = dateFormat.Split(' '); 
       string[] spd = sps[0].Split('.'); 
       dateFormat = spd[0] + ":" + spd[1] + " " + sps[1]; 
       DateTime dt = new DateTime(); 
       dt = Convert.ToDateTime(dateFormat); 
       return dt.Hour.ToString("00") + dt.Minute.ToString("00"); 
      } 
      catch (Exception ex) 
      { 
       return "Enter Correct Format like <5.12 pm>"; 
      } 
     } 

     private void button2_Click(object sender, EventArgs e) 
     { 
      label2.Text = ConvDate_as_date(textBox2.Text); 
     } 

     public string ConvDate_as_date(string stringFormat) 
     { 
      try 
      { 
       string hour = stringFormat.Substring(0, 2); 
       string min = stringFormat.Substring(2, 2); 
       DateTime dt = new DateTime(); 
       dt = Convert.ToDateTime(hour+":"+min); 
       return String.Format("{0:t}", dt); ; 
      } 
      catch (Exception ex) 
      { 
       return "Please Enter Correct format like <0559>"; 
      } 
     } 
    } 
} 
4

ответ Одед является хорошим, но это не работает для меня даты UTC. Чтобы заставить его работать для дат UTC, мне нужно было указать значение DateTimeStyles для «RoundtripKind», чтобы он не пытался предположить, что это было местное время. Вот обновленный код сверху:

const string FMT = "O"; 
DateTime now1 = DateTime.Now; 
string strDate = now1.ToString(FMT); 
DateTime now2 = DateTime.ParseExact(strDate, FMT, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); 
Console.WriteLine(now1.ToBinary()); 
Console.WriteLine(now2.ToBinary()); 

Примечание. Это работает как для UTC, так и для местных дат.