将C#日期时间转换为字符串并反向转换

34

我正在将C#的日期时间转换为字符串。稍后当我将其转换回DateTime对象时,发现它们不相等。

我将C#的日期时间转换为字符串,但是当我尝试将其转换回DateTime对象时,它们似乎不相等。

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

小细节:如果您要使用"InvariantCulture"解析字符串,那么为了安全起见,您可能也想将"InvariantCulture"传递到ToString方法中:now1.ToString(FMT, CultureInfo.InvariantCulture); - Dr. Wily's Apprentice
5个回答

48
如果您想保留 DateTime 的值,建议使用 Oo 格式说明符。

Oo 是一个标准格式说明符,它表示使用一种模式的自定义日期和时间格式字符串以保留时区信息。 对于 DateTime 值,该格式说明符旨在将日期和时间值与 DateTime.Kind 属性一起以文本形式保存。 如果样式参数设置为 DateTimeStyles.RoundtripKind,则可以使用 DateTime.Parse(String, IFormatProvider, DateTimeStyles) 或 DateTime.ParseExact 方法将格式化的字符串解析回来。

使用您的代码(除了更改格式字符串):

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

2
我在使用这个方法时遇到了UTC日期的问题。请看下面我是如何解决的。 - Taylor Lafrinere

19

Oded的答案很好,但对于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());

注意,这适用于协调世界时和当地日期。


日期类型非常重要。 - diegosasw

2
如果您不需要将字符串变得可读(例如,您想在存储之前加密它),则可以调用string str = dt1.ToBinary().ToString();DateTime dt2 = DateTime.FromBinary(long.Parse(str));
DateTime now1 = DateTime.Now;
string strDate = now1.ToBinary().ToString();
DateTime now2 = DateTime.FromBinary(long.Parse(strDate));
Console.WriteLine(now1.ToBinary());
Console.WriteLine(now2.ToBinary());

2

两个问题:

  1. You can use the ParseExact overload that takes a DateTimeStyle parameter in order to specify AssumeLocal.

  2. There will still be a small difference between now1 and now2 unless you increase the precision to 7 digits instead of 3: "yyyy-MM-dd HH:mm: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());
    

即使没有上述更改,现在1和现在2之间计算出的差异似乎很小,尽管二进制值看起来并不相似。

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

谢谢。我需要获得完全相同的值,任何差异都会导致单元测试失败,因此最好使用“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>";
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接