【问题标题】:Parsing any valid DateTime format to SQL Server compatible format?将任何有效的 DateTime 格式解析为 SQL Server 兼容格式?
【发布时间】:2013-04-25 09:58:37
【问题描述】:

我来自印度,在这里我们遵循dd-mm-yyyy 日期格式。

我的问题是,我们的各种客户需要他们的日期时间以上述格式显示。但是我们用作后端的 SQL Server 不将 dd-mm-yyyy 识别为有效的日期时间格式。我们通常做的是使用 CultureInfo 将给定日期转换为 mm-dd-yyyy 或者使用 Convert.ToDateTime() or DateTime.Parse or DateTime.TryParse()

另外,我遇​​到了另一种情况,当我输入的日期格式正确时说MM-dd-yyyy or MM/dd/yyyy or yyyy-MM-dd,但我的本地系统日期不是上面的,然后是it throws exception, input string in not in correct format。我无法弄清楚如何自动解决它。

现有的自定义方法:但在大多数情况下,这会失败。

 /// <summary>
    /// Parses string value from a supplied value to DateTime.
    /// Usage: var i = Common.ParseDate(yourDateString);
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    private static DateTime ParseDate(string value)
    {
        DateTime i;
        if (!DateTime.TryParse(value, out i))
            return Convert.ToDateTime("01/01/1700",CultureInfo.InvariantCulture); 
// Assuming 01/01/1700 as default value instead of null.
        return i;
    }

请建议更改上述内容,以便我的方法自动将任何日期时间转换为 SQL Server 兼容格式,如 yyyy-mm-dd。

用法应该是这样的:

Input:
DateTime dt = DateTimeParser("29-12-2013"); // in case or double figure months and dates

Output of dt: either 2013-12-29 or 12/29/2013

DateTime dt = DateTimeParser("9-2-2013"); // in case or single figure months and dates

Output of dt: either 2013-2-9 or 2/9/2013 (sql-server compatible)

请注意:日期时间转换应与系统时钟无关。

提前致谢

【问题讨论】:

  • 你的用户用什么方式输入日期?
  • @lavrik dd/mm/yyyy 或 dd-mm-yyyy。另一个主要问题是我的 Windows 时钟日期时间格式。如果它与用户输入不同,则会引发异常
  • 所以视图和逻辑之间没有层。值得为正确的日期时间输入创建用户控件。这是我认为最好的方法:允许用户在同一个应用程序范围的标准中输入数据,因此您对逻辑的输入应该是 DateTime 实例而不是最早执行步骤中的字符串。您创建什么样的应用程序 - 网络桌面等?
  • 一般是网络应用。但我还没有得到关于系统时钟问题的答案。如果我的代码格式是mm-dd-yyyy,windows日期时间是dd-mm-yyyy,会抛出异常???
  • 答案是,如果是 Web 应用程序,您必须正确绑定表单中的 DateTime 实例。这是主要目标。而且您不需要手动解析字符串 - 如果您向用户提供输入日期的唯一方法。否则,您将头疼处理用户当前的文化,例如 DateTime.Parse("", CultureInfo.GetCultureInfo("de-De"/*user's one here*/)) 或迭代可能的格式。

标签: c# .net visual-studio-2010 c#-4.0 datetime


【解决方案1】:

我曾经想要这个确切的东西,尽管我们能够假设用户的意思,因为正确性并不重要(对于像 MS Excel 这样的东西,当你输入文本日期时间时)。

实际上,您可以从内置文化中收集所有可能的日期时间格式,以及您可以自己定义的许多自定义格式。我曾经想要一个非常全面的日期时间格式匹配。

我做了一些与 nawfal 的回答非常相似的事情。这是一个将他的答案与我的大量格式相结合的解决方案:

static string[] GetDateTimeFormats()
{
    var defaultFormats = CultureInfo.GetCultures(CultureTypes.AllCultures)
                                    .SelectMany(x => x.DateTimeFormat.GetAllDateTimePatterns())
                                    .Distinct(); //to speed up things

    //discard some formats that're not worthy of consideration
    var goodDefaultFormats = defaultFormats.Where(x => !IsPoorFormat(x) && !IsConflictingFormat(x));

    var customFormats = GetCustomDateTimeFormats();

    var allFormats = goodDefaultFormats.Concat(customFormats).ToArray();

    //a technique to get comma separated time formats, 
    //for eg, from dd-MM-yyyy h:mm:ss tt we get -> dd-MM-yyyy, h:mm:ss tt
    var moreCustomFormats = allFormats.Select(f => new 
                                      { 
                                          f, 
                                          i = f.IndexOf(" h", StringComparison.OrdinalIgnoreCase) 
                                      })
                                      .Where(x => x.i >= 0)
                                      .Select(x => new { x.f, c = x.f[x.i - 1], x.i })
                                      .Where(x => !char.IsPunctuation(x.c) && x.c != 't')
                                      .Select(x => x.f.Insert(x.i, ","));

    allFormats = allFormats.Union(moreCustomFormats).ToArray(); //Union removes duplicates

    return allFormats;
}

static bool IsPoorFormat(string format)
{
    //all discardable formats in case any
    string[] ignorables = { "HH", "MMMM yyyy", "MMMM, yyyy", "yyyy MMMM", "yyyy.M", "yyyy-MM", 
                            "MMMM,yy", "MMMM, yy", "MMMM,yyyy", "MMMM, yyyy", "yyyy. MMMM" };

    return ignorables.Contains(format);
}

//to remove conflicting date formats, for example, 
//formats like MM-dd-yy, yy-MM-dd, dd-MM-yy etc can be conflicting
static bool IsConflictingFormat(string format)
{
    //in this example we discard formats like M-d-yy, yy-MM-dd etc, but keep dd-MM-yy
    //in case you want to keep MM-dd-yy, the placeholders array should be { 'd', 'y' },
    //and similarly if the preferred format is yy-MM-dd, array should be { 'M', 'd' }
    var placeholders = new[] { 'M', 'y' };

    var separators = new[] { ' ', '.', '-', '/' };

    var patterns = placeholders.Select(x => x.ToString())
                               .SelectMany(x => new[] { x, x + x })
                               .SelectMany(x => separators, (x, y) => x + y);

    return patterns.Any(format.StartsWith);
}

static string[] GetCustomDateTimeFormats()
{
    return new[] 
    {
        "dddd, MMMM d, yyyy h:mm:ss tt",
        "dddd, MMMM d, yyyy H:mm:ss",
        "dddd, MMMM d, yyyy h:mm tt",
        "dddd, MMMM d, yyyy H:mm",

        "dddd, MMM d, yyyy h:mm:ss tt",
        "dddd, MMM d, yyyy H:mm:ss",
        "dddd, MMM d, yyyy h:mm tt",
        "dddd, MMM d, yyyy H:mm",

        "ddd, MMMM d, yyyy h:mm:ss tt",
        "ddd, MMMM d, yyyy H:mm:ss",
        "ddd, MMMM d, yyyy h:mm tt",
        "ddd, MMMM d, yyyy H:mm",

        "ddd, MMM d, yyyy h:mm:ss tt",
        "ddd, MMM d, yyyy H:mm:ss",
        "ddd, MMM d, yyyy h:mm tt",
        "ddd, MMM d, yyyy H:mm",



        "dddd, MMMM d yyyy h:mm:ss tt",
        "dddd, MMMM d yyyy H:mm:ss",
        "dddd, MMMM d yyyy h:mm tt",
        "dddd, MMMM d yyyy H:mm",

        "dddd, MMM d yyyy h:mm:ss tt",
        "dddd, MMM d yyyy H:mm:ss",
        "dddd, MMM d yyyy h:mm tt",
        "dddd, MMM d yyyy H:mm",

        "ddd, MMMM d yyyy h:mm:ss tt",
        "ddd, MMMM d yyyy H:mm:ss",
        "ddd, MMMM d yyyy h:mm tt",
        "ddd, MMMM d yyyy H:mm",

        "ddd, MMM d yyyy h:mm:ss tt",
        "ddd, MMM d yyyy H:mm:ss",
        "ddd, MMM d yyyy h:mm tt",
        "ddd, MMM d yyyy H:mm", 

        ///////////////////////////

        "dddd, d MMMM, yyyy h:mm:ss tt", 
        "dddd, d MMMM, yyyy H:mm:ss", 
        "dddd, d MMMM, yyyy h:mm tt", 
        "dddd, d MMMM, yyyy H:mm", 

        "dddd, d MMM, yyyy h:mm:ss tt", 
        "dddd, d MMM, yyyy H:mm:ss", 
        "dddd, d MMM, yyyy h:mm tt", 
        "dddd, d MMM, yyyy H:mm", 

        "ddd, d MMMM, yyyy h:mm:ss tt", 
        "ddd, d MMMM, yyyy H:mm:ss", 
        "ddd, d MMMM, yyyy h:mm tt", 
        "ddd, d MMMM, yyyy H:mm", 

        "ddd, d MMM, yyyy h:mm:ss tt", 
        "ddd, d MMM, yyyy H:mm:ss", 
        "ddd, d MMM, yyyy h:mm tt", 
        "ddd, d MMM, yyyy H:mm", 



        "dddd, d MMMM yyyy h:mm:ss tt", 
        "dddd, d MMMM yyyy H:mm:ss", 
        "dddd, d MMMM yyyy h:mm tt", 
        "dddd, d MMMM yyyy H:mm", 

        "dddd, d MMM yyyy h:mm:ss tt", 
        "dddd, d MMM yyyy H:mm:ss", 
        "dddd, d MMM yyyy h:mm tt", 
        "dddd, d MMM yyyy H:mm", 

        "ddd, d MMMM yyyy h:mm:ss tt", 
        "ddd, d MMMM yyyy H:mm:ss", 
        "ddd, d MMMM yyyy h:mm tt", 
        "ddd, d MMMM yyyy H:mm", 

        "ddd, d MMM yyyy h:mm:ss tt", 
        "ddd, d MMM yyyy H:mm:ss", 
        "ddd, d MMM yyyy h:mm tt", 
        "ddd, d MMM yyyy H:mm", 

        /////////////////////////////////

        "yyyy, MMMM d h:mm:ss tt", 
        "yyyy, MMMM d H:mm:ss", 
        "yyyy, MMMM d h:mm tt", 
        "yyyy, MMMM d H:mm", 

        "yyyy, MMM d h:mm:ss tt", 
        "yyyy, MMM d H:mm:ss", 
        "yyyy, MMM d h:mm tt", 
        "yyyy, MMM d H:mm", 

        "yyyy, MM d h:mm:ss tt", 
        "yyyy, MM d H:mm:ss", 
        "yyyy, MM d h:mm tt", 
        "yyyy, MM d H:mm", 



        "yyyy MMMM d h:mm:ss tt", 
        "yyyy MMMM d H:mm:ss", 
        "yyyy MMMM d h:mm tt", 
        "yyyy MMMM d H:mm", 

        "yyyy MMM d h:mm:ss tt", 
        "yyyy MMM d H:mm:ss", 
        "yyyy MMM d h:mm tt", 
        "yyyy MMM d H:mm", 

        "yyyy MM d h:mm:ss tt", 
        "yyyy MM d H:mm:ss", 
        "yyyy MM d h:mm tt", 
        "yyyy MM d H:mm", 

        ///////////////////////

        "yyyy, d MMMM h:mm:ss tt", 
        "yyyy, d MMMM H:mm:ss", 
        "yyyy, d MMMM h:mm tt", 
        "yyyy, d MMMM H:mm", 

        "yyyy, d MMM h:mm:ss tt", 
        "yyyy, d MMM H:mm:ss", 
        "yyyy, d MMM h:mm tt", 
        "yyyy, d MMM H:mm", 

        "yyyy, d MM h:mm:ss tt", 
        "yyyy, d MM H:mm:ss", 
        "yyyy, d MM h:mm tt", 
        "yyyy, d MM H:mm", 



        "yyyy d MMMM h:mm:ss tt", 
        "yyyy d MMMM H:mm:ss", 
        "yyyy d MMMM h:mm tt", 
        "yyyy d MMMM H:mm", 

        "yyyy d MMM h:mm:ss tt", 
        "yyyy d MMM H:mm:ss", 
        "yyyy d MMM h:mm tt", 
        "yyyy d MMM H:mm", 

        "yyyy d MM h:mm:ss tt", 
        "yyyy d MM H:mm:ss", 
        "yyyy d MM h:mm tt", 
        "yyyy d MM H:mm",

        ////////////////////////////////

        "MMMM d, yyyy h:mm:ss tt",
        "MMMM d, yyyy H:mm:ss",
        "MMMM d, yyyy h:mm tt",
        "MMMM d, yyyy H:mm",

        "MMM d, yyyy h:mm:ss tt",
        "MMM d, yyyy H:mm:ss",
        "MMM d, yyyy h:mm tt",
        "MMM d, yyyy H:mm",



        "MMMM d yyyy h:mm:ss tt",
        "MMMM d yyyy H:mm:ss",
        "MMMM d yyyy h:mm tt",
        "MMMM d yyyy H:mm",

        "MMM d yyyy h:mm:ss tt",
        "MMM d yyyy H:mm:ss",
        "MMM d yyyy h:mm tt",
        "MMM d yyyy H:mm",

        ////////////////////////////////////

        "d MMMM, yyyy h:mm:ss tt", 
        "d MMMM, yyyy H:mm:ss", 
        "d MMMM, yyyy h:mm tt",
        "d MMMM, yyyy H:mm",  

        "d MMM, yyyy h:mm:ss tt", 
        "d MMM, yyyy H:mm:ss", 
        "d MMM, yyyy h:mm tt",
        "d MMM, yyyy H:mm",  



        "d MMMM yyyy h:mm:ss tt", 
        "d MMMM yyyy H:mm:ss", 
        "d MMMM yyyy h:mm tt",
        "d MMMM yyyy H:mm",  

        "d MMM yyyy h:mm:ss tt", 
        "d MMM yyyy H:mm:ss", 
        "d MMM yyyy h:mm tt",
        "d MMM yyyy H:mm",  

        /////////////////////////

        "dddd, MMMM d, yyyy",
        "dddd, MMM d, yyyy",

        "ddd, MMMM d, yyyy",
        "ddd, MMM d, yyyy",



        "dddd, MMMM d yyyy", 
        "dddd, MMM d yyyy",

        "ddd, MMMM d yyyy",
        "ddd, MMM d yyyy",

        //////////////////////////

        "dddd, d MMMM, yyyy", 
        "dddd, d MMM, yyyy", 

        "ddd, d MMMM, yyyy", 
        "ddd, d MMM, yyyy",  



        "dddd, d MMMM yyyy",
        "dddd, d MMM yyyy",

        "ddd, d MMMM yyyy", 
        "ddd, d MMM yyyy", 

        ///////////////////////////

        "MMMM d, yyyy",
        "MMM d, yyyy",

        "MMMM d yyyy",
        "MMM d yyyy",

        //////////////////////////

        "d MMMM, yyyy", 
        "d MMM, yyyy",

        "d MMMM yyyy", 
        "d MMM yyyy",

        //////////////////////////

        "yyyy, MMMM d", 
        "yyyy, MMM d", 

        "yyyy MMMM d", 
        "yyyy MMM d", 

        //////////////////////////

        "yyyy d MMMM", 
        "yyyy d MMM", 

        "yyyy, d MMMM", 
        "yyyy, d MMM", 

        ///////////////////////////

        "d MMMM",
        "d MMM",

        /////////////////////////////

        "MMMM d", 
        "MMM d",

        ////////////////////////////

        "dd",
    };
}

【讨论】:

    【解决方案2】:

    您无需将日期解析为格式。使用 SQL Server 中的 DateTime 数据类型作为字段,与格式无关。还要确保在通过 C# 与 SQL Server 交互时使用SqlParameterDateTime 格式只能用于显示日期。喜欢:

    using(SqlConnection conn = new SqlConnection("connectionstring"))
    using (SqlCommand cmd = new SqlCommand())
    {
        cmd.CommandText = "Insert into yourtable(datecolumn) VALUES (@pDate);";
        cmd.Parameters.AddWithValue("@pDate", DateTime.Now);
        cmd.Connection = conn;
        //.....
    }
    

    【讨论】:

    • 我已经试过了。但是我的代码本身会从后面的代码中抛出异常。我不是在这里谈论 SQL 异常。
    • @AmitRanjan,我不明白。 SQL DateTime 与格式无关,如 .Net 日期时间。您在解析客户输入的日期时遇到异常吗?
    • 是的,当我们以本地格式显示 SQL 日期并将它们保存回相应的 DateTime 属性时,我在代码级别遇到错误。..
    • cmd.Parameters.AddWithValue("@pDate", DateTime.Now);我可以像这样使用它吗 cmd.Parameters.AddWithValue("@pDate", "30-12-2013");它会工作吗?假设 datecolumn 在 SQL 中是 DateTime 类型
    • 您可以从 SQL 服务器检索 DateTime 到 .Net DateTime,然后为了显示您可以使用自定义格式,如 dt.ToString("dd/MM/yyyy");
    【解决方案3】:

    我个人使用参数。否则你可以force a particular DateTime format in SQL Server

    【讨论】:

      【解决方案4】:

      尝试此代码如果您的输入日期是“dd/mm/yyyy”,那么它会转换 Sql 兼容格式,否则它会为您提供消息日期格式不是预期的格式。

       var dd = string.Empty;
          var mm = string.Empty;
          var yy = string.Empty;
          string actualDate = "18/07/2012";
          string finalDate = string.Empty;
          if (actualDate.ToString().Contains('/'))
          {
              dd = string.Format("{0:00}", Convert.ToInt32(actualDate.ToString().Split('/')[0]));
              mm = string.Format("{0:00}", Convert.ToInt32(actualDate.ToString().Split('/')[1]));
              yy = string.Format("{0:0000}", Convert.ToInt32(actualDate.ToString().Split('/')[2]));
              finalDate = dd + "/" + mm + "/" + yy;
          }
      
          string dateString = finalDate; // <-- Valid
          string format = "dd/MM/yyyy";
          DateTime dateTime;
          if (!DateTime.TryParseExact(dateString, format, CultureInfo.InvariantCulture,
              DateTimeStyles.None, out dateTime))
          {
             lblDate.Text= "Excel Date is not correct format.it should be in dd/mm/yyyy";
          }
          else
          {
              actualDate =
                  DateTime.ParseExact(dateString, format,
                                         CultureInfo.InvariantCulture,
                                         DateTimeStyles.None).ToString();
          }
      
          Label1.Text = actualDate;
      

      【讨论】:

        【解决方案5】:

        正如 Habib 所说,要将其保存在数据库中,您不需要知道任何格式,只需保存 DateTime 对象,您的 ado.net 连接器就会知道如何处理它。

        您的问题应该在于将用户的输入字符串解析为 .NET DateTime 对象。现在不知道用户的文化特定设置,你注定要失败。你不能有一个通用的方法来处理它。考虑日期12/12/12,它可能意味着dd/MM/yyMM/dd/yy 或任何其他组合。


        您最好的选择是获取有关用户、他的文化的信息并进行相应的解析。或者要求他以您指定的格式输入。


        好吧,你可以依靠一些启发式方法来匹配常见的格式,假设格式 但它完全脆弱。仅当准确性不是问题时,这才很方便

        private static DateTime ParseOrDefault(string value)
        {
            DateTime result;
            var sett = DateTimeStyles.AllowWhiteSpaces; //and whatever that is
            var formats = GetDateTimeFormats //whatever cultures that you want to consider.
            (
                new CultureInfo("en-GB"), //prioritize your order
                new CultureInfo("en-IN"), 
                CultureInfo.CurrentCulture, 
                CultureInfo.InvariantCulture
            );
        
            if (!DateTime.TryParseExact(value, formats, CultureInfo.InvariantCulture, sett, out result))
                return Convert.ToDateTime("01/01/1700", CultureInfo.InvariantCulture);
        
            return result;
        }
        
        string[] GetDateTimeFormats(params CultureInfo[] cultures)
        {
            return cultures.SelectMany(x => x.DateTimeFormat.GetAllDateTimePatterns())
                           .Distinct()
                           .ToArray();
        }
        

        DateTime.ParseExactDateTime.TryParseExact 具有重载以实现对多种格式的匹配。上述方法假设来自用户的输入字符串首先在en-GBen-IN 等文化中,即在12/12/12 的情况下,它会将其视为dd/MM/yy。这是一些假设,但在不知道输入的情况下您可以得到尽可能接近的结果,而您唯一的选择就是假设。 小心。

        这样称呼:

        Common.ParseOrDefault(yourDateString);
        

        另一个选项可能是您匹配所有可能的格式,您知道不包括冲突格式。例如,如果您只想考虑 dd/MM/yy 格式,您可以过滤掉 MM/dd/yyyy/MM/dd 格式。现在您可以获得大量格式并避免冲突。可以稍微好一点。

        static string[] formats; //made static for performance reasons
        
        private static DateTime ParseOrDefault(string value)
        {
            formats = formats ?? GetDateTimeFormats();
        
            DateTime result;
            var sett = DateTimeStyles.AllowWhiteSpaces; //and whatever that is
        
            if (!DateTime.TryParseExact(value, formats, CultureInfo.InvariantCulture, sett, out result))
                return Convert.ToDateTime("01/01/1700", CultureInfo.InvariantCulture);
        
            return result;
        }
        
        static string[] GetDateTimeFormats()
        {
            var allFormats = CultureInfo.GetCultures(CultureTypes.AllCultures)
                                        .SelectMany(x => x.DateTimeFormat.GetAllDateTimePatterns())
                                        .Distinct(); //to speed up things
        
            //discard some formats that're not worthy of consideration
            var goodFormats = allFormats.Where(x => !IsConflictingFormat(x));
        
            return goodFormats.ToArray();
        }
        
        //to remove conflicting date formats, for example, 
        //formats like MM-dd-yy, yy-MM-dd, dd-MM-yy etc can be conflicting
        static bool IsConflictingFormat(string format)
        {
            //in this example we discard formats like M-d-yy, yy-MM-dd etc, but keep dd-MM-yy
            //in case you want to keep MM-dd-yy, the placeholders array should be { 'd', 'y' },
            //and similarly if the preferred format is yy-MM-dd, array should be { 'M', 'd' }
            var placeholders = new[] { 'M', 'y' };
        
            var separators = new[] { ' ', '.', '-', '/' };
        
            var patterns = placeholders.Select(x => x.ToString())
                                       .SelectMany(x => new[] { x, x + x })
                                       .SelectMany(x => separators, (x, y) => x + y);
        
            return patterns.Any(format.StartsWith);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-02
          • 2021-12-09
          • 1970-01-01
          • 1970-01-01
          • 2012-03-13
          • 1970-01-01
          相关资源
          最近更新 更多