asp.net datetime随机复制时间偏移量。是个bug?

时间:2015-10-01 09:31:04

标签: asp.net datetime datetimeoffset

我有一个在asp.net 4和sql server 2008 R2中开发的网站。 问题非常复杂。 我在db中有一个数据时间偏移UTC的字段(例如2015-09-30 18:24:53.1498113 +02:00)。 随机(我认为当应用程序池重新启动时)此值在.net中查询后返回损坏,如下所示: 30/09/2015 18:21:00 +02:00 +02:00 时间偏移重复2次!

所以,当我在c#中解析日期时,显然我收到一个错误“字符串未被识别为有效的DateTime”。

如果我回收池applcation页面工作正常

为什么呢?这是一个错误?你见过类似的问题吗?

非常感谢

5 个答案:

答案 0 :(得分:2)

今天我们也遇到过这种情况 - 我第一次见到它。这绝对不是Alex的错误,它是一个强类型的DateTimeOffset,带有沼泽标准.ToString(),它将偏移量加两次。它只发生在我们的一个Web服务器上,如果我们启动它,我预计它会消失。我肯定明确地为ToString提供一个字符串格式可以防止它再次出现,并且可能会出现某种类型的操作系统级别的损坏,因为我已经看到默认格式随操作系统升级而变化(在这种情况下可能会赢得'当我们踢它时,我会得到修复。)

答案 1 :(得分:2)

我们在IIS上托管的asp.net-mvc应用程序(.NET 4.5)中观察到了相同的行为。其中一个服务器在这个看似无害的代码中从razor cshtml中的模型序列化DateTimeOffset值时开始生成重复的偏移量(几周没有部署版本):

@Html.HiddenFor(m => m.CreateDate)
<span>@Model.CreateDate</span>

在这两个地方都生成了重复的偏移量,如2017-11-20 12:34 +01:00 +01:00。 重新启动IIS池解决了这个问题,但我不知道将来如何避免它。

答案 2 :(得分:1)

在我们的一项WCF服务中观察到类似的行为-我们的特定情况是使用Newtonsoft.Json从传入请求中反序列化了DateTimeOffset值,并使用DateTimeOffset.ToString()将其转换为字符串,最后得到的字符串表示形式如下所示

  public class EditProfileController : Controller
{

    private readonly ApplicationDbContext db;
    private object _context;

    public EditProfileController(ApplicationDbContext Db)
    {
        db = Db;
    }
    public IActionResult Index()
    {
      List<ApplicationUser> listdata = db.Users
        .Select(user => new ApplicationUser()
        {
            Id =  user.Id,
            UserName = user.UserName,
            NormalizedUserName = user.NormalizedUserName,
                            Email = user.Email


            // Add the remainder properties
        }).ToList();
    return View(listdata);
    }
    [HttpGet]
    public ActionResult Edit(string id)
    {
        //Get user and return the Edit View
        ApplicationUser user = db.Users.Where(u => u.Id == id)
      .Select(u => new ApplicationUser()
      {
          Id = u.Id,
          UserName = u.UserName,
          NormalizedUserName = u.NormalizedUserName,
          Email = u.Email

          // Add the remainder properties
      }).FirstOrDefault();
        return View(user);
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(ApplicationUser listdata)
    {
        if (ModelState.IsValid)
        {
            db.Entry(listdata).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(listdata);
    }


    public async Task<IActionResult> Delete(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        var user = await db.Users
            .FirstOrDefaultAsync(m => m.Id == id);
        if (user == null)
        {
            return NotFound();
        }

        return View(user);
    }


    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> DeleteConfirmed(int id)
     {
        var user = await db.Users.FindAsync(id);
        db.Users.Remove(user);
        await db.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
     }
  }

我们的第一个假设显然是这是我们代码中的错误-它始终是您的代码,对吧?但是,我们在结束时非常详尽地跟踪了执行情况,并且找不到自己可能导致此问题的任何可能的方式-很难相信,看来MM/dd/yyyy 12:00:00 AM -04:00 -04:00 的结果实际上只是在返回那个服务器上的字符串格式。

导致最终错误的特定字符串转换发生在内部框架中,因此我们只是换掉了转换方式,因此我们现在使用显式字符串格式。没有确认是否可行。我们的替换实现如下所示-

DateTimeOffset.ToString

我们的短期解决方案是重新启动IIS应用程序池-两次都遇到该问题后,该问题立即停止出现。

答案 3 :(得分:1)

这是由于DateTimeOffset的ToString()方法中的竞争条件引起的。之所以引起竞争,是因为在构建模式字符串时,代码直接针对dateTimeOffsetPattern成员起作用。模式字符串是短日期和长时间模式的串联。有些文化在长时间模式中包含偏移量,因此代码会对此进行检查。在字符串中不包含偏移量的情况下,它将连接偏移量格式,如下所示:

if (!foundZ) {
    dateTimeOffsetPattern = dateTimeOffsetPattern + " zzz";
}

根据执行顺序,有时它会执行两次或在一个线程中执行,而不是在另一个线程中执行。

此问题已在.Net Framework的较新版本中修复,但可以通过提供自己的格式字符串来解决。

答案 4 :(得分:-1)

当我们尝试解析使用DateTimeOffset.toString()值转换的字符串时,会发生同样的问题。 ADO.Net客户端转换中的DateTimeOffset.toString()返回具有重复Offset值的无效DateTimeOffset格式。我们停止了DateTimeOffset的字符串转换,并开始直接使用DateTimeOffset对象。