MongoTemplate实现根据时间等条件组合查询日期范围

Java和Mongo中的Date比较(数据库默认是UTC标准时间)

由于中国处于东八区(GMT+08:00)是比世界协调时间/格林尼治时间(GMT)快8小时的时区,当格林尼治标准时间为0:00时,东八区的标准时间为08:00。

时间戳是一个数字,定义为格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。注意,同一时刻,不同时区获得的时间戳是相同的。以前很多用来记录时间的字段,在数据库中往往不会存储为Datetime类型,而是直接存储为无符号整形,存放时间戳的值。

Java中的东八区Date:"updateTime" : ("2023-12-06T10:13:49.427")
MongoDB中的UTC标准时间Date: "updateTime" : ISODate("2023-12-06T02:13:49.427Z")

MongoDB中的日期格式 是 UTC 通用标准,以z来标识,格式为yyyy-MM-dd HH:mm:ss.000Z
该时间比中国北京时间晚了8个小时,即ISODate("2023-12-06T02:13:49.427Z")相当于北京时间2023-12-06T10:13:49.427

因为mongo中的Date类型以UTC(Coordinated Universal Time)存储,就等于GMT(格林尼治标准时)时间。而系统时间使用的是GMT+0800时间,两者正好相差8个小时。

包含日期字段实体类的封装

Book book= mongoTemplate.findOne(new Query(Criteria.where("_id").is("656fd8dde0c34e57defdc8d2")), Book.class);
System.out.println(book);

在这里插入图片描述
mongoTemplate查询时将MongoDB中的UTC Date类型自动转为东八区时间。
如果MongoDB配置的是LocalTinezone,也就是当前时区即东八区,则java不会再转换。

日期范围查找(查找更新时间在昨天零时至今天零时的图书)

即在2023-12-06零点-2023-12-07零点2023-12-06T00:00:00.000-2023-12-07T00:00:00.000的图书

Mongodb数据库查询:

因为MongoDB中的Date类型比中国北京时间晚了8个小时,所以24-8=16查找内容为小于ISODate("2023-12-06T16:00:00.000Z")大于ISODate("2023-12-05T16:00:00.000Z")

db.book.find({
  updateTime: {$lte: ISODate("2023-12-06T16:00:00.000Z"),$gte: ISODate("2023-12-05T16:00:00.000Z")}
})

在这里插入图片描述
或者使用东八区时间来查,虽然配置的是UTC但是会自动将东八区转为UTC时间来查。

db.book.find({
  updateTime: {$lte: ISODate("2023-12-07T00:00:00.000+08:00"),$gte: ISODate("2023-12-06T00:00:00.000+08:00")}
})

在这里插入图片描述
以下为错误示范,这相当于查的是北京时间2023-12-06T08:00:00.000-2023-12-07T08:00:00.000的图书

db.book.find({
  updateTime: {$lte: ISODate("2023-12-07T00:00:00.000Z"),$gte: ISODate("2023-12-06T00:00:00.000Z")}
})

在这里插入图片描述

Java

第一种:

 Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        Query query = new Query();
        Criteria criteria = Criteria.where("updateTime").lte(c.getTime());
        c.add(Calendar.DAY_OF_MONTH, -1);
        criteria.gte(c.getTime());
        query.addCriteria(criteria);
        List<Book> books = mongoTemplate.find(query, Book.class);
        books.stream().forEach(book -> System.out.println(book));

原理:

在这里插入图片描述
java会将北京时间自动转为MongoDB中的Date类型。
将北京时间2023-12-06T00:00:00.000-2023-12-07T00:00:00.000转换为2023-12-05T16:00.00Z-2023-12-06T16:00.00Z
mongoTemplate以UTC生成的Query语句去数据库中查询。
在这里插入图片描述
第二种:

        LocalDateTime startTime = LocalDateTime.now().minusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime EndTime = startTime.plusDays(1);
        Query query = new Query(Criteria.where("updateTime").lte(EndTime).gte(startTime));
        List<Book> books = mongoTemplate.find(query, Book.class);
        books.stream().forEach(book -> System.out.println(book));

原理:

在这里插入图片描述
mongoTemplate以东八区生成的Query语句去数据库中查询,此时会自动将东八区转为UTC时间来查。
在这里插入图片描述

MongoDB条件表达式

表达式含义
$gt>
$gte>=
$eq=
$ne!=
$lt<
$lte<=
$inin(后面的值为bson对象数组)
$ninnot in(后面的值为bson对象数组)

实现方式1:

Query query = new Query(Criteria.where("updateTime").lte(LocalDateTime.now()).gte(LocalDateTime.now().minusMonths(5)));
Book book = mongoTemplate.findOne(query, Book.class);

实现方式2:

BasicDBObject query = new BasicDBObject();
BasicDBObject basicDbObject = new BasicDBObject();
LocalDateTime startTime = LocalDateTime.now();
basicDbObject.append("$lte", startTime);
basicDbObject.append("$gte", startTime.minusMonths(5));
query.put("updateTime", basicDbObject);
long countDocuments = mongoTemplate.getCollection("book").countDocuments(query);
System.out.println(countDocuments);

实现方式3:

BasicDBObject gt = new BasicDBObject("$gt",24);
BasicDBObject queryObject = new BasicDBObject("age",gt);

这个BasicDBObject 类就是bson jar包的类,这里的条件拼接出来就是下面这个格式
{"age":{"$gt":24}}
如果转换为MongoDB指令 也就是db.java.find({"age":{"$gt":24}})

int startYear=2011;  
int startMonth=11;  
int startDay=1; 
BasicDBObject ageObj = new BasicDBObject("insertTime",new BasicDBObject("$gte",new Date(startYear - 1900, startMonth - 1, startDay)));

因为BasicDBObject()这个构造函数会自动帮你把Date格式数据转换为UTC通用标准时
注意:因为java.util.Date(year,month,day)这个构造函数中year是超出1900的年数,所以需要减去1900;month从0开始,所以需要减去1。

然后测试上面的代码,发现成功,日期可以筛选出来,如果我们需要是 日期大于2011-1-1 并且 小于 2012-12-12呢?

我们只需要做如下操作即可,参数自己替换

BasicDBObject ageObjStart = new BasicDBObject("updateTime",new BasicDBObject("$gte",new Date(startYear - 1900, startMonth - 1, startDay)));
BasicDBObject ageObjEnd = new BasicDBObject("updateTime",new BasicDBObject("$lte",new Date(endYear - 1900, endMonth - 1, endDay)));
BasicDBObject andObj = new BasicDBObject("$and",Arrays.asList(ageObjStart ,ageObjEnd ));

然后就可以实现筛选介于两个时间点内的数据了!

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MongoDB中存储的时间是UTC时间,而Java中的日期时间默认是使用系统默认时区的时间。因此,在使用Java代码查询MongoDB中的时间时,需要将Java时间转换为UTC时间,或将MongoDB中的时间转换为Java时间并指定时区。 您可以使用Java 8中的`java.time`包中的`Instant`和`ZoneOffset`类来进行时间转换。以下是一个示例代码,用于查询MongoDB中`timestamp`字段大于某个时间的文档: ```java import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import java.time.Instant; import java.time.ZoneOffset; import java.util.Date; import java.util.List; public class Example { private MongoTemplate mongoTemplate; public List<Document> findDocumentsByTimestamp(Date timestamp) { Instant instant = timestamp.toInstant().atZone(ZoneOffset.systemDefault()).withZoneSameInstant(ZoneOffset.UTC).toInstant(); Criteria criteria = Criteria.where("timestamp").gt(Date.from(instant)); Query query = Query.query(criteria); return mongoTemplate.find(query, Document.class); } } ``` 在上面的代码中,我们首先将Java的`Date`对象转换为`Instant`对象,然后使用`ZoneOffset.systemDefault()`获取系统默认时区,并将其转换为UTC时区的`Instant`对象。接着,我们将转换后的`Instant`对象转换为`Date`对象,并将其用于构建查询条件。最后,我们使用`MongoTemplate`的`find`方法执行查询并返回结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值