将LDAP中的WhenChanged属性(一般化时间)转换为C#中的DateTime

11
我最近从使用S.DS命名空间(该命名空间使用ADSI)切换到S.SD.Protocol命名空间。唯一的问题是,ADSI为我处理了从Generalized-Time到DateTime的转换。现在,当我获取WhenChanged属性时,返回值是“20070828085401.0Z”。但是,DateTime.Parse()无法将其转换,那么还有其他方法吗?
4个回答

8
你得到的格式接近于往返日期时间模式("o")和通用可排序往返日期时间模式("u")标准日期时间格式字符串,如此处所述。
一种笨拙的解决方法是对获取到的字符串进行处理以适应该模式,然后使用"o"或"u"标准格式字符串与ParseExact一起使用。
更好的方法是构建一个自定义格式字符串,以匹配您已经获取到的数据。在标准日期时间格式字符串页面的"标准格式字符串工作原理"部分中,您将看到完整的自定义格式字符串相当于"o"和"u"。这应该能为您提供一个良好的开端。

编辑: 添加代码

string format = "yyyyMMddHHmmss.f'Z'";

string target = "20070828085401.0Z";

DateTime d = DateTime.ParseExact(target, format, CultureInfo.InvariantCulture);

在评论中,lixonn 指出,使用上述格式字符串,ParseExact 将无法成功解析时间字符串,例如 199412160532-0500
它也无法解析许多其他有效的字符串,例如没有尾随的 'Zulu' 指示符的时间(20070828085401.0);没有小数部分的时间(20070828085401Z)和将分钟和秒表示为小数小时的时间(2007082808.90028Z)。
通过用 K 自定义格式指定项 替换硬编码的 'Z',可以使格式字符串稍微宽容一些,该指定项将接受 'Z'、偏移量(如 -0500)和空值。这种额外的灵活性是否有益取决于应用程序。
请注意,即使使用了 K 指定项,Lixonn 的字符串也无法成功解析,因为它缺少与格式字符串的 .f 组件匹配的小数部分。

根据:https://tools.ietf.org/html/rfc4517#section-3.3.13 这将无法通过:199412160532-0500 - lixonn

3

您需要使用 DateTime.ParseExact() 方法并指定精确格式。您可能需要尝试不同的格式,但大致如下。

DateTime result;
CultureInfo provider = CultureInfo.InvariantCulture;
string format="yyyyMMddhhmmss.0Z";
result = DateTime.ParseExact(dateString, format, provider);

1
// WIN32 FILETIME is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
// While the unix timestamp represents the seconds since January 1, 1970 (UTC).
private static long Win32FileTimeToUnixTimestamp(long fileTime)
{
    //return fileTime / 10000L - 11644473600000L;
    return DateTimeOffset.FromFileTime(fileTime).ToUnixTimeSeconds();
}

// The GeneralizedTime follows ASN.1 format, something like: 20190903130100.0Z and 20190903160100.0+0300
private static long GeneralizedTimeToUnixTimestamp(string generalizedTime)
{
    var formats = new string[] { "yyyyMMddHHmmss.fZ", "yyyyMMddHHmmss.fzzz" };
    return DateTimeOffset.ParseExact(generalizedTime, formats, System.Globalization.CultureInfo.InvariantCulture).ToUnixTimeSeconds();
}

1
你可以使用datetime的.strptime()
    import datetime

    # Since 0Z denotes UTC, you can get rid of it and apply the timezone 
    # later if you would like
    time_string = "20070828085401.0Z".split('.')[0]
    time_object = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%S")

time_object 应该输出为 datetime.datetime(2007, 8, 28, 8, 54, 1)。我认为它将是时区无关的,并等同于UTC时间。


1
问题的标题和标签清楚地表明OP在谈论C#,而不是Python。因此,这个答案在这里是不恰当的。 - Alexandre

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