Nodatime对Instant.FromDateTimeUtc的DateTime.Kind无效

Jan*_*nik 1 c# datetime nodatime

我试图了解我们所遇到的这个时区问题.我们希望以UTC格式存储所有日期时间,然后将日期时间转换为用户时区.

我们决定使用Nodatime,因为它似乎是正确的方法.但是我们遇到了一些问题

这就是我们将datetime转换为UTC的方法(注意:我现在硬编码了usersTimeZone)

public static DateTime ConvertLocaltoUTC(this DateTime dateTime)
{
    LocalDateTime localDateTime = LocalDateTime.FromDateTime(dateTime);

    IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;
    var usersTimezoneId = "Europe/Copenhagen";
    var usersTimezone = timeZoneProvider[usersTimezoneId];

    var zonedDbDateTime = usersTimezone.AtLeniently(localDateTime);
    var returnThis = zonedDbDateTime.ToDateTimeUtc();
    return zonedDbDateTime.ToDateTimeUtc();
}
Run Code Online (Sandbox Code Playgroud)

以下是我们如何将其转换回来的方式

public static DateTime ConvertUTCtoLocal(this DateTime dateTime)
{
    Instant instant = Instant.FromDateTimeUtc(dateTime);
    IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;
    var usersTimezoneId = "Europe/Copenhagen"; //just an example
    var usersTimezone = timeZoneProvider[usersTimezoneId];
    var usersZonedDateTime = instant.InZone(usersTimezone);
    return usersZonedDateTime.ToDateTimeUnspecified();
}
Run Code Online (Sandbox Code Playgroud)

但是当我们将它转​​换回本地时,它会引发异常:

参数异常:Instant.FromDateTimeUtc的DateTime.Kind无效

在"ConvertUTCtoLocal()"的第一行,日期时间的一个例子可能是:"9/18/2017 5:28:46 PM" - 是的,这是通过ConvertLocalToUTC方法.

我提供了错误的格式,或者我在这里做错了什么?

Mat*_*int 8

您展示的例外情况:

参数异常:Instant.FromDateTimeUtc的DateTime.Kind无效

从这段代码抛出:

Instant instant = Instant.FromDateTimeUtc(dateTime);
Run Code Online (Sandbox Code Playgroud)

这意味着dateTime.Kind需要DateTimeKind.Utc转换为a Instant,无论出于何种原因,它都不是.

如果你查看你的ConvertLocaltoUTC方法的结果,你会发现它确实有.Kind == DateTimeKind.Utc.

所以,问题出在你的代码的其他地方,无论你在哪里创建了dateTime你传入的代码ConvertUTCtoLocal.

您可能会发现解决方案可能是以下任何一种:

  • 您可能需要调用DateTime.SpecifyKind将类型设置为UTC,但请注意,只有在您的值实际为UTC且仅设置类型时才执行此操作.例如,在DateTime从数据库加载基于UTC时使用此选项.

  • 您可能需要致电.ToUniversalTime(),但如果机器的当地时区与您的情况相关,请务必小心.例如,在UI控件选择日期的桌面或移动应用程序中执行此操作,但您的意思是它表示UTC而不是本地时间.

  • 您可能需要更改将字符串解析为DateTime值的方式,例如通过传递DateTimeStyles.RoundTripKind给DateTime.Parse调用(或其任何变体).例如,如果要从text,csv等中读取数据,请执行此操作.

如果您想避免必须决定,请不要编写DateTime作为输入或DateTime作为输出的函数.相反,使用DateTimeOffset,或者使用野田时间类型,如Instant,LocalDateTime等趁早.


Chr*_*row 6

这对我有用:

Instant instant = Instant.FromDateTimeUtc(DateTime.SpecifyKind(datetime, DateTimeKind.Utc));
Run Code Online (Sandbox Code Playgroud)