在Mongodb使用过程中,发现一个问题,就是我们插入Date类型时会发现保存到mongodb中的数据却晚了8个小时,这是为什么呢?我想大家在使用客户端工具如MongoVUE时,也会发现查询出来的数据也是晚了8个小时的?下面简单描述下原因。

上面的两个问题,我们依次来看是为什么?

(1)在Java编码过程中,使用mongodb的java驱动包保存数据时,数据库里的数据比实际时间少了8个小时,为什么?

为了找打原因,我下载了个mongodb的java驱动包,想通过驱动包来找到原因,驱动包如下:

我们都知道,mongodb数据库是基于文档的,每个文档都是一个类json格式的,那么肯定在保存到数据库时进行了某种json序列化操作,我们朝着这个方向去找到相关的序列化类,我们在com.mongodb.util包下看到一个JSON类,在这个类里有如下逻辑进行序列化:

public static String serialize(Object object)
  {
    StringBuilder buf = new StringBuilder();
    serialize(object, buf);
    return buf.toString();
  }

  public static void serialize(Object object, StringBuilder buf)
  {
    JSONSerializers.getLegacy().serialize(object, buf);
  }

可见,对于任何类型是先找到相对应的序列化类(有点像hessian、fastjson的实现),然后调用对应的序列化类对对象Object进行序列化操作。

我们在JSONSerializers这个类内部看到这么一段:

serializer.addObjectSerializer(Date.class, new LegacyDateSerializer(serializer));

这句用于将java.util.Date类型与LegacyDateSerializer序列化类进行了绑定,使用该类对java.utl.Date类型进行序列化,我们看看是怎么序列化的:

private static class LegacyDateSerializer extends JSONSerializers.CompoundObjectSerializer
  {
    LegacyDateSerializer(ObjectSerializer serializer)
    {
      super();
    }

    public void serialize(Object obj, StringBuilder buf)
    {
      Date d = (Date)obj;
      SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
      format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT")));
      this.serializer.serialize(new BasicDBObject("$date", format.format(d)), buf);
    }
  }

从代码可以看出来,其实对于我们的Date类型都是转换为国际标准时间GMT的,而我们的时区是东八区(GMT+8),因此经过转换为时间少了8个小时,在数据库中看到的也就少了8个小时。

现在我们知道了原因,那么这种情况影不影响我们的业务呢?没有影响的,因为在我们读取的时候mongodb的java驱动同样为我们做了相应的转换工作。


(2)使用MongoVue客户端软件操作mongodb数据库时看到的数据和实际保存时间相差8个小时为什么?

其实,通过上面的描述我们其实很容易理解看到的数据为什么少了8个小时,但是怎样才能看到我们实际的时间呢?

在Tools下面有个Preferences;


选择Views,可以看到我们这时候选择的是UTC;

这时候我们需要选择成上面的,使用本地时区进行显示:

这时候我们就可以在这个客户端工具中看到时间我们插入的时间是一致的了。Do you get it? ^_^


备注:尊重原创,如需转载请标明出处,谢谢。

Logo

前往低代码交流专区

更多推荐