【问题标题】:How to Convert Stringified Date Value in format Month/Day/Year Time as a DateTime?如何将月/日/年时间格式的字符串化日期值转换为日期时间?
【发布时间】:2021-01-28 23:32:20
【问题描述】:

我有一个包含两个 DateTime 成员的类。

但是,当我尝试将表示日期的“人类可读”值分配给 DateTime 成员时,它会拒绝它并显示消息“字符串未被识别为有效的 DateTime”。

失败的代码行是:

md.BeginDate = DateTime.Parse(reader.GetValue(5).ToString());

在上下文中,显示我尝试从 DateTime 的字符串表示形式转换的值:

根据此处的第一个和接受的答案 [https://stackoverflow.com/questions/2193012/string-was-not-recognized-as-a-valid-datetime-format-dd-mm-yyyy],我也试过这个:

md.BeginDate = DateTime.ParseExact(reader.GetValue(6).ToString(), "MM/dd/yyyy", null); 

...但同样可耻的结果。

更新

基于this,我尝试了以下方法:

CultureInfo provider = CultureInfo.InvariantCulture;
string format = "yyyy-MM-dd HH:mm:ss.ffffff";
. . .
DateTime.ParseExact(dateString, format, provider);

...但得到相同的结果。

“dateValAsStr”的值为2021-01-21 11:25:56.9608384

更新 2

事实证明,这是我的一个非常愚蠢的疏忽。当我单步执行时,我看到数据库中的 Date (TEXT) 值是空的。所以这段代码“有效”(不抛出异常):

CultureInfo provider = CultureInfo.InvariantCulture;
string format = "yyyy-MM-dd HH:mm:ss.fffffff";
. . .
string qry = "SELECT LocationName, Address1, City, StateOrSo, PostalCode, " +
                        "BeginDate, EndDate, MapDetailNotes, Latitude, Longitude " +
                        "FROM CartographerDetail " +
                        "WHERE FKMapName = @FKMapName";
. . .
dateValAsStr = reader.GetValue(5).ToString().Trim();
if (! String.IsNullOrWhiteSpace(dateValAsStr))
{
    md.BeginDate = DateTime.ParseExact(dateValAsStr, format, provider).Date;
}
dateValAsStr = reader.GetValue(6).ToString().Trim();
if (!String.IsNullOrWhiteSpace(dateValAsStr))
{
    md.EndDate = DateTime.ParseExact(dateValAsStr, format, provider).Date;
}

【问题讨论】:

  • 您要检索的列的类型是什么?如果数据库中已经是日期/时间,使用md.BeginDate = reader.GetDateTime(5);转换成字符串再解析是自找麻烦。完全避免格式问题。
  • 如果我没记错的话,SQLite advises storing dates in ISO-8601 format。如果数据库不遵循该约定,请显示示例数据。
  • 好的,所以它遵循约定。尽管它与答案显示的格式不同,但您链接的答案如何没有帮助?我在您的代码中没有看到对 DateTime.ParseExact 的调用。
  • 解析它 with 时间部分(包括 all 7 f 地方...你只有 6 个地方),然后取Date结果的属性来删除时间部分。
  • 你不需要 ParseExact,Parse 就足够了:var date = DateTime.Parse("2021-01-21 11:25:56.9608384", CultureInfo.InvariantCulture);

标签: c# datetime datetime-format


【解决方案1】:

你给出的简单例子是这样的:

string dateString = "2021-01-21 11:25:56.9608384";
CultureInfo provider = CultureInfo.InvariantCulture;
string format = "yyyy-MM-dd HH:mm:ss.fffffff";
DateTime result = DateTime.ParseExact(dateString, format, provider);

请注意,秒的小数位数是 7,但您的 format 只有 6 fs。

如果你改成7fs 就可以了。

【讨论】:

  • @B.ClayShannon - 是的,但你只有 6 个 fs - 你需要其中的 7 个。
  • @B.ClayShannon - UPDATE 2 是您问题的答案吗?
  • @B.ClayShannon - 然后请发布作为问题的答案并将其从问题本身中删除。然后您可以将其标记为已接受的答案。
  • 如果您的输入中的小数位数可能不同,您应该使用FFFFFFF(7 个大写F 字符),它可以正确解析0 到7 位小数的输入。否则,这个答案看起来不错。另见图表on this docs page。
  • @Enigmativity:我想将赏金奖励给某人。
【解决方案2】:

如果您有时间的毫秒大小长度不一致,请尝试我使用的这种方法,该方法用于我们提供这种不一致时间的系统。

public static string DynamicMillisecondDateTimeFormat(string date)
{
    var size = date[(date.LastIndexOf(".", StringComparison.Ordinal) + 1)..].Length;
    var fs = new string('f', size);
    return size == 19 ? "yyyy-MM-dd HH:mm:ss" : $"yyyy-MM-dd HH:mm:ss.{fs}";
}

要对此进行测试,请执行以下操作:

string[] dates = {
    "2021-01-21 11:25:56",
    "2021-01-21 11:25:56.9",
    "2021-01-21 11:25:56.96",
    "2021-01-21 11:25:56.960",
    "2021-01-21 11:25:56.9608",
    "2021-01-21 11:25:56.96083",
    "2021-01-21 11:25:56.960838",
    "2021-01-21 11:25:56.9608384"
};

var provider = CultureInfo.InvariantCulture;

foreach (var date in dates)
{
    var format = DynamicMillisecondDateTimeFormat(date);
    DateTime.TryParseExact(date, format, provider, DateTimeStyles.None, out var dateTime);
    Console.WriteLine(dateTime.ToString(format));
}

如果我们根据您的情况考虑,您可以执行以下操作:

var format = DynamicMillisecondDateTimeFormat(ReaderOptions.GetValue(5).ToString());
bool parsable = DateTime.TryParseExact(date, format, provider, DateTimeStyles.None, out var dateTime);
if (parsable)
{
    md.BeginDate = date;
}

顺便说一句,link 有一些关于日期时间格式的有趣信息。

除了感谢@MattJohnson-Pint 的评论并让我意识到我的DynamicMillisecondDateTimeFormat 方法的更好替代方法,您只需执行以下格式,它将自动采用 0 到 7 之间的所有毫秒长度。注意它应该有大写 Fs:

"yyyy-MM-dd HH:mm:ss.FFFFFFF"

【讨论】:

  • 这是很好的开箱即用的想法,但没有必要。只需使用 FFFFFFF(7 个大写字母 F 字符)。它将正确解析 0 到 7 位小数的输入。
  • @MattJohnson-Pint 我已经用它更新了我的问题,我也测试了它。很好很酷的方式。祝您度过愉快的一天,再次感谢您的提示。
【解决方案3】:

您可以像这样创建一个新的 DateTime,方法是将 reader.GetValue(5) 拆分到适当的插槽中

int d1 = 200;
int d2 = 2;
int d3 = 24;
DateTime datet = new DateTime(d1,d2,d3);
md.BeginDate = datet;

d1、d2 和 d3 是您需要用从 getvalue 拆分的数据替换的内容

【讨论】:

  • 谢谢;毕竟我可能不得不求助于这种“蛮力”方法
【解决方案4】:

我会改用Parse。 Microsoft Documentation中有一系列很好的例子

(string dtStr, string descr)[]  dateInfo = { 
      ("08/18/2018 07:22:16", "String with a date and time component"),
      ("08/18/2018", "String with a date component only"),
      ("8/2018", "String with a month and year component only"),
      ("8/18", "String with a month and day component only"),
      ("07:22:16", "String with a time component only"),
      ("7 PM", "String with an hour and AM/PM designator only"),
      ("2018-08-18T07:22:16.0000000Z", "UTC string that conforms to ISO 8601"),
      ("2018-08-18T07:22:16.0000000-07:00", "Non-UTC string that conforms to ISO 8601"),
      ("Sat, 18 Aug 2018 07:22:16 GMT", "String that conforms to RFC 1123"),
      ("08/18/2018 07:22:16 -5:00", "String with date, time, and time zone information" ) };

Console.WriteLine($"Today is {DateTime.Now:d}\n");

foreach (var i in dateInfo) {
  Console.WriteLine($"'{i.dtStr}' = {DateTime.Parse(i.dtStr)} {i.descr+ ":",-52}");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    相关资源
    最近更新 更多