改变DateTimeOffset.Offset属性?

Change DateTimeOffset.Offset Property?

我的最终目标是从客户端获取没有偏移的通用时间 - 只是 UTC 时间。我尝试这样做:

Javascript: (new Date()).toUTCString(), which logs 的输出: Thu, 17 Mar 2016 15:13:23 GMT, 这正是我需要的。

然后我将它带到服务器并尝试将其转换为 DateTimeOffset:

string dateTimeOffsetPattern = "ddd, dd MMM yyyy HH:mm:ss 'GMT'"; 

DateTimeOffset clientLoginTime = DateTimeOffset.ParseExact
    (timeStringFromClient, dateTimeOffsetPattern, CultureInfo.InvariantCulture);

这导致:

3/17/2016 3:13:23 PM -04:00 

它以某种方式调整了我当地(东部)偏移的时间。我不希望这种情况发生,我希望它只是 return UTC 时间,就像这样:

3/17/2016 3:13:23 PM +00:00

P.S。我只是问了另一个问题,我很抱歉,因为我觉得这应该很容易,但我不明白。这应该非常简单,但看起来像 offset doesn't have a setter(除非我像往常一样完全缺少一些 C# 基础知识):

public TimeSpan Offset { get; }

有一个 overload of ParseExact where you can specify a DateTimeStyles. DateTimeValues 的值之一是 AssumeUniversal,表示:

If format does not require that input contain an offset value, the returned DateTimeOffset object is given the UTC offset (+00:00).

这基本上意味着 "don't assume it's local, assume it's universal." 假设本地是默认值,这就是为什么您看到的结果是适应本地的。指定 AssumeUniversal 应该按照您想要的方式解析它。

DateTimeOffset clientLoginTime = DateTimeOffset.ParseExact
(timeStringFromClient, dateTimeOffsetPattern, CultureInfo.InvariantCulture, 
    DateTimeStyles.AssumeUniversal);

从 JavaScript(或任何其他客户端)您应该使用 ISO8601 format which would be yyyy-MM-ddTHH-mm-ss.sssz. The Z indicates that the datetime instance is GMT (UTC). You can also change this to add + or - from GMT. You can do this using the JavaScript Date object using myDate.toISOString()

发送 DateTimes

创建 WebAPI 模型时,您可以直接使用 DateTimeDateTimeOffset 类型。 JSON.NET Web API 序列化器会自动将发送的 ISO8601 日期时间字符串反序列化为正确的 DateTime 或 DateTimeOffset 类型(取决于您使用的是哪一种)。这意味着您不必在代码中进行任何手动解析,这很好。 (想象一下,如果您必须将所有内容作为字符串发送并在所有方法中手动解析所有内容?)。

所以你现在可以有一个方法

public async Task<IHttpActionResult> GetRecords(DateTimeOffset? startFrom)

并且 startFrom 将根据发送的 ISO8601 格式的 DateTime 字符串自动填充。

最后,这样做的最后一个也是最重要的原因是您的客户可能不会都使用相同的语言环境。您可能有一个用户将他们的浏览器设置为西班牙语,因此 .toUTCString() 不会产生英文字符串,甚至可能不会产生带有 mm/dd 的字符串,而是相反(就像美国以外的大多数国家一样)。

网络长话短说API

  • 使用 ISO8601 from/to 客户端。
  • 直接在模型中使用 DateTimeOffset 或 DateTime 实例(不解析)。

我会正常从 JS 解析,然后执行以下操作:

  • 通过返回 DateTime
  • DateTimeOffset 中删除 OffSet
  • 通过实例化另一个 DateTimeOffset 并将 TimeSpan 设置为 ZERO 来设置 OffSet

你的情况:

var clientLoginTime = new DateTimeOffset(clientLoginTime.DateTime, TimeSpan.FromHours(0));

这可以很容易地转换成扩展方法

public static DateTimeOffset SetOffset(this DateTimeOffset dto, int timeZoneDiff)
{
    return new DateTimeOffset(dto.DateTime, TimeSpan.FromHours(timeZoneDiff));
}