将 dd/MM/yyyy 转换为 yyyy/MM/dd?

4

我想将字符串 '30/12/2012' 转换为 '2012/12/30'。我的应用程序设置为 "en-CA",但数据库默认接受 yyyy/MM/dd。

如何在不依赖于服务器上当前文化信息的情况下完成此操作?


你能发布一下发送日期到数据库的代码吗? - Kobi
目前业务对象中是字符串,数据库中是日期。 - Zo Has
3
如果可能的话,我会将其升级为BO中的DateTime / DateTimeOffset...如果您将其保留为DateTime,则可以将其作为DateTime传递到数据库(更好),或者使用一个简单的“yyyy/MM/dd”格式字符串(在一个位置)。 - user166390
为什么不在您的业务对象中使用DateTime? - dan_l
1
如果数据库中的数据类型为日期(Date),则不必在代码后台将其转换为字符串。从字符串输入创建一个DateTime对象,为您的SQL存储过程/脚本创建一个参数,并在参数中指定该值为DateTime类型。 - rikitikitik
显示剩余4条评论
6个回答

13

正如所有的评论所说,但迄今为止没有一个答案提到:不要将此作为字符串传递给数据库

尽早将收到的任何文本解析,然后使用 DateTime 表示它在任何其他地方,包括通过参数化 SQL1 将其发送到数据库的方式。这适用于所有类型的值:尽早将其转换为数据的“自然”类型,并尽可能长时间地保持在该自然表示中。日期不是字符串,只有在真正需要时才将其转换为字符串 - 最好是在将其显示给用户之前 仅仅

可以使用 DateTime.ParseExactDateTime.TryParseExact 进行解析,具体取决于数据是否“可疑”(例如来自用户)或应该确实正确并且无法解析的值最合适的反应是异常。建议您在自定义格式字符串中传递 CultureInfo.InvariantCulture。例如:

DateTime date = DateTime.ParseExact(text, "dd/MM/yyyy",
                                    CultureInfo.InvariantCulture);

(如果你需要大量处理日期/时间,你可能还想考虑使用我的Noda Time项目,它允许你以更丰富的方式表达值 - 在这种情况下,你可能会使用LocalDate。)


1 如果你还没有使用参数化SQL,而是直接将值嵌入SQL中,那么你比日期/时间转换更有大问题。


那是一条非常出色的建议,Jon。我花了一天时间来纠正业务对象和数据访问层,但这是值得努力的。我完全按照你的建议去做,现在我没有经常弹出的转换错误了。对于这个出色的建议,我竖起大拇指,并且我喜欢这里的讨论,Damein =) - Zo Has
@DamienJoe:太好了-很高兴它对你有用。尽可能长时间地坚持使用最自然的表示原则已经变得非常重要了。 - Jon Skeet

4
如果格式一直都是相同的,那么就按照斜杠/进行分割。
string[] tempsplit = datestring.Split('/');

然后重新组装它。
string joinstring = "/";
string newdate = tempsplit[2] + joinstring + tempsplit[1] + joinstring + tempsplit[0];

简单。


1
这会导致一个越界异常。如果你使用了大写字母 S 的 Split('/'),结果将是 "20120620"。老实说,我几乎总是测试我公开发布的代码。 - Kobi
是的,我完全明白你的意思 :) - Kobi
1
可能是 datestring.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)。 - dan_l
为什么要手动处理(接受无效数据,例如20个月),而不是使用DateTime解析然后重新格式化? - Jon Skeet

4
您可以在Format和大多数ToString函数中指定CultureInfo。
例如,DateTime.ToString(CultureInfo)DateTime.Parse(string, CultureInfo)将让您在一个文化环境中(例如当前或new CultureInfo("en-CA"))解析字符串,并在另一个文化环境中格式化,如new CultureInfo("en-us")
注意:您可以考虑通过设置Thread.CurrentCulture在某些其他文化环境下运行所有DB访问(例如en-US),因为有时数字格式也会受到影响(如果数字存储为字符串)。

2
首先,使用以下方法将您的字符串转换为DateTime格式:
DateTime dt = Convert.ToDateTime("your string value");

然后使用以下代码将其存储为字符串:

string st=dt.ToString("yyyy/MM/dd");

这将把您的日期格式转换为任何您想要的格式,而不依赖于文化背景。


2
Convert.ToDateTime确实依赖于文化。否则它怎么能理解05/06/2012是什么意思呢?是5月6日还是6月5日?(您的ToString调用对于日期分隔符也依赖于文化。) - Jon Skeet
@Jon Skeet 我同意你的观点,但问题在于他想要一个解决方案,将任何DateTime格式转换为所需的格式,并且不需要提及文化信息。针对这一部分,我编写了以下代码: 这将把您的日期格式转换为任何您想要的格式,而不依赖于文化。 - user1465587

1

这似乎可行。

        var x = new string[] { "2012/06/12", "20/06/2012", "111/111/1111" };
        foreach (var ds in x)
        {
            DateTime d = default(DateTime);
            try
            {
                d = DateTime.Parse(ds, CultureInfo.GetCultureInfo("en-CA"));
            }
            catch (Exception ex)
            {
                try
                {
                    d = DateTime.ParseExact(ds, "yyyy/MM/dd", CultureInfo.InvariantCulture);
                }
                catch
                {
                }
            }
            if (d == default(DateTime))
                Console.WriteLine("error");
            else
                Console.WriteLine(d.ToString());
        }

你的变量x已经是我想要的格式了。我尝试过,但对于“20/06/2012”它并没有起作用。 - Zo Has
刚刚编辑了代码,它很丑。你可以考虑使用TryParse()方法。 - dan_l
感谢您的代码dan_I。虽然我采纳了Jon Skeet的建议,但我确实把您的代码作为我的数据层参考。唯一的问题是输入字符串必须与指定格式相同。+1 - Zo Has

1

不需要考虑数据库接受什么格式的问题,您可以按照以下方式进行转换:

  • 将字符串转换为日期时间,例如在此处解释
  • 更改格式并再次将其转换为字符串,例如这里

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