MongoDB 的奇怪日期行为

Posted

技术标签:

【中文标题】MongoDB 的奇怪日期行为【英文标题】:Strange date behaviour with MongoDB 【发布时间】:2017-02-15 04:39:55 【问题描述】:

我正在编写一个使用 MongoDB 作为其数据库的 React 应用程序。从数据库中保存和检索日期时,特别是在更新特定文档中的日期时,似乎有一些奇怪的行为。

当我创建一个新文档时,一切都很好。但是,如果我尝试使用 ajax 调用编辑该文档上的日期,则存储在 MongoDB 中的日期比我选择的日期和浏览器中显示的日期早一天。下面的代码解释一下。

使用 html5 <input type='date' /> 元素选择日期。这是一些代码。我在各个点包含控制台日志以显示输出。假设我选择“2016 年 10 月 30 日”作为日期。日期和年份被分开用于在其他地方显示,但在发送到服务器之前以 JS Date 对象的形式连接在一起(参见下面的代码)

React 组件方法:

saveChanges(e, cancel)
        e.preventDefault();
        const cancelled = cancel ? true : false

        console.log(this.state.date); // 30 Oct
        console.log(this.state.year); // 2016

        const saveData = 
            id: this.props.data.id,
            venue: this.state.venue,
            unitNumber: this.state.unitNumber,
            unitName: this.state.unitName,
            date: this.state.date,
            year: this.state.year,
            day: this.state.day,
            tutorID: this.state.tutorID,
            cancelled: cancelled
        

        editWorkshop(saveData, (data) => 
            this.props.getWorkshopDetails();
            this.props.workshopDetailsSaved(data);
        );

    

上述方法将数据发送到editWorkshop.js,外部ajax调用,使用axios

import axios from 'axios';

export default function editWorkshop(input, callback)

    const date = new Date(input.date + ' ' + input.year) // Rejoin date and year and convert to Date object
    console.log(date); // Sun Oct 30 2016 00:00:00 GMT+0100 (BST)
    const data = 
        id: input.id,
        venue: input.venue,
        unitNumber: input.unitNumber,
        unitName: input.unitName,
        date: date,
        day: input.day,
        tutorID: input.tutorID,
        cancelled: input.cancelled
    

    axios.post('/editWorkshop', data).then(function(res)
        callback(res.data); 
        )
    

最后是处理 ajax 调用的 express 路由

const express = require('express');
const Workshop = require('../data/models/Workshop');

module.exports = function(req, res)

    const data = req.body
    console.log(data.date); // 2016-10-29T23:00:00.000Z - here is where it seems to go wrong - notice that the date has changed to 2016-10-29 instead of 10-30. This now gets written to the database
    Workshop.update( _id: data.id , 
        $set: 
            unitNumber: data.unitNumber,
            date: data.date,
            venue: data.venue,
            tutor: data.tutorID,
            session: data.day,
            cancelled: data.cancelled
        
    , function(err)
        if (err) 
            res.send(err);
            return
        
        var message = 'Workshop updated'
        res.send(
            success: true,
            message: message
        );
    )


真正奇怪的是,当我从应用程序其他地方的数据库中检索数据时,它在浏览器中显示正确的日期 - 2016 年 10 月 30 日。

可以说这不是问题,因为正在显示正确的日期,但我对此并不满意,因为这些日期是应用程序的基本组成部分,我担心可能存在错误未来。

任何人都可以对此有所了解吗?

【问题讨论】:

【参考方案1】:

2016-10-29T23:00:00.000ZSun Oct 30 2016 00:00:00 GMT+0100 (BST) 相同。

2016-10-29T23:00:00.000Z 位于UTC(GMT) 时区。如果将其转换为 BST,您将获得相同的值。

MongoDB 将日期值保存为自纪元以来的 UTC 毫秒数。

来自docs:

MongoDB 默认以 UTC 存储时间,并将转换任何本地时间 时间表示成这种形式。必须运行的应用程序或 报告某些未修改的本地时间值可能会存储时区 在 UTC 时间戳旁边,并计算原始本地时间 他们的应用逻辑。

【讨论】:

太好了,谢谢 - 只要日期存储正确,我就可以忍受这种差异,我只是想确保将来不会出现潜在的错误。 我遇到了同样的问题,但在 Java 中,SimpleDateFormat 类没有可以用(BST)解析的格式,在我的情况下,日期的格式是`“dateCreated”:“2021- 05-08T15:37:48.882Z[UTC]' 我不知道如何解析,一种方法是手动删除 [UTC],但这似乎不对。

以上是关于MongoDB 的奇怪日期行为的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB“连接失败。操作正在进行中”

Mongodb如何获取单个文档的大小?

Mongodb 找到错误的结果 Int64 对象

mongodb:获取 API POST 请求返回一个奇怪的响应

Mongodb 文档中不存在的字段出现在 mongoose findById() 结果中

MongoDB - _id 索引大小的奇怪差异