【问题标题】:Saving Datetimeoffset on Azure SQL not working在 Azure SQL 上保存 Datetimeoffset 不起作用
【发布时间】:2017-09-19 21:36:20
【问题描述】:

我在使用 Azure SQL 服务器时遇到问题,在我的本地计算机上,我可以将 datetimeoffset 保存到数据库中,并且时区偏移量已正确保存,例如 下面

2017-03-31 00:00:00.0000000 -05:00

但是在 azure 上丢失了时区偏移量,我的列是 datetimeoffset 类型,我正在使用 DateTimeOffset.UtcNow.UtcDateTimeDateTimeOffset.Now 获取我的 datetimeoffset 但似乎两种方法都不起作用,总是像下面这样保存

2017-03-31 00:00:00.0000000 +00:00

如何在 Azure SQL 服务器上保存正确的 DateTimeOffset。

编辑:我正在使用实体框架代码优先迁移,我只是创建实体并使用上面的任何一行分配 DateTimeOffset,然后使用 context.SaveChanges()。

var entity = Mapper.Map<CarSearchForm, CarSearches>(model);
 ctx.CarSearches.Add(entity);
 ctx.SaveChanges();

然后automapper配置文件是这样的

CreateMap<CarSearchForm, CarSearches>()
            .ForMember(dest => dest.RequestedDate, opts => opts.MapFrom(src => DateTimeOffset.UtcNow.UtcDateTime))
            .ForMember(dest => dest.PickupTime, opts => opts.MapFrom(src => src.TimePickup))
            .ForMember(dest => dest.DropoffTime, opts => opts.MapFrom(src => src.TimePickup));    

这是模型

namespace Data.Entities
{
    public class CarSearches
    {
        public int CarSearchesId { get; set; }
        [Required]
        public string PickupPlace { get; set; }
        [Required]
        public DateTimeOffset PickupDate { get; set; }
        [Required]
        public DateTimeOffset PickupTime { get; set; }
        [Required]
        public DateTimeOffset DropoffDate { get; set; }
        [Required]
        public DateTimeOffset DropoffTime { get; set; }       
        [Required]
        public CarTransmission Transmission { get; set; }
        [Required]
        public DateTimeOffset RequestedDate { get; set; }        
    }

}

我只对上面的 RequestedDate 属性感兴趣,我不知道为什么不在 Azure 上保存时区偏移量而是在本地工作。

谢谢

【问题讨论】:

  • 如何使用保存到数据库?英孚? ado.net?由于某种原因,您的日期时间中缺少时间部分
  • 显示代码如何保存
  • 我进行了编辑,我使用的是 EF 代码优先迁移,没什么特别的,只是创建实体并分配值和 ctx.SaveChanges()
  • 您正在将其投射到某处的date
  • 向我们展示您的代码优先模型。

标签: c# sql-server azure datetimeoffset


【解决方案1】:

...我正在使用 DateTimeOffset.UtcNow.UtcDateTimeDateTimeOffset.Now 获取我的 datetimeoffset

  • 第一个总是会给你一个 UTC DateTime 值(偏移量+00:00)。相当于DateTime.UtcNow

  • 第二个会给你一个DateTimeOffset 值,它的本地时间和偏移量与运行它的计算机相匹配。

    • 在您的本地计算机上,您会看到 -05:00,因为它使用您计算机的本地时区设置。

    • 在 Azure 上,您会看到 +00:00。这是因为大多数 Azure 服务器和服务都设置了以 UTC 运行的时区。

      一般来说,这是服务器的best practice,尤其是云中的服务器。服务器经常需要与世界各地的客户端连接,并相互交换数据。 UTC 是唯一合理的时区。

另一种思考方式是,如果机器的时区设置为 UTC,DateTime.NowDateTime.UtcNow 将给出相同的日期和时间值,但将其 .Kind 属性设置为 @987654335 @ 和另一个将其设置为DateTimeKind.Utc。由于DateTimeOffset 没有Kind(谢天谢地),因此在时区设置为UTC 的机器上无法区分DateTimeOffset.NowDateTimeOffset.UtcNow

至于如何处理 - 如果您希望考虑其他时区,您首先必须知道是哪个时区。然后,您可以使用 TimeZoneInfo 类(如果您使用 Windows 时区)或 Noda Time 库(如果您使用 IANA 时区)将当前 UTC 时间转换为 DateTimeOffset特定时区。

使用TimeZoneInfo

DateTime utcNow = DateTime.UtcNow;
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTimeOffset easternNow = TimeZoneInfo.ConvertTimeFromUtc(utcNow, tz);

使用Noda Time

Instant now = SystemClock.Instance.Now;
DateTimeZone tz = DateTimeZoneProviders.Tzdb["America/New_York"];
DateTimeOffset easternNow = now.InZone(tz).ToDateTimeOffset();

【讨论】:

  • 关于天蓝色时区及其工作原理的非常详细的解释,基于我得到以下信息,始终将日期时间存储在 UTC 上,并在我的应用程序代码上手动指定时区转换为本地日期时间。
  • 是的,没错。考虑到您的代码应该表现出相同的行为并记录相同的数据,而不管它托管在哪里或服务器碰巧在什么时区设置上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-14
  • 1970-01-01
  • 2016-10-09
  • 2018-10-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
相关资源
最近更新 更多