24

我有一个 MongoDB,它以 UTC 存储日期对象。好吧,我想在不同的时区 (CET) 中按年月日执行聚合。

这样做,适用于 UTC:

    BasicDBObject group_id = new BasicDBObject("_id", new BasicDBObject("year", new BasicDBObject("$year", "$tDate")).
                append("month", new BasicDBObject("$month", "$tDate")).
                append("day", new BasicDBObject("$dayOfMonth", "$tDate")).
                append("customer", "$customer"));

    BasicDBObject groupFields = group_id.
            append("eventCnt", new BasicDBObject("$sum", "$eventCnt")); 

    BasicDBObject group = new BasicDBObject("$group", groupFields);

或者,如果您使用命令行(未测试,我只测试了 java 版本):

{
    $group: {
        _id: {
            "year": {
                "$year", "$tDate"
            },
            "month": {
                "$month", "$tDate"
            },
            "day": {
                "$dayOfMonth", "$tDate"
            },
            "customer": "$customer"
        },
        "eventCount": {
            "$sum": "$eventCount"
        }
    }
}

如何在聚合框架内将这些日期转换为 CET?

例如“2013-09-16 23:45:00 UTC”是“2013-09-17 00:45:00 CET”,这是不同的一天。

4

8 回答 8

16

我不是 CET 及其与 UTC 关系的专家,但以下代码(用于 shell)应该对 MongoDB 日期类型进行适当的转换(增加一个小时):

db.dates.aggregate(
  {$project: {"tDate":{$add: ["$tDate", 60*60*1000]}, "eventCount":1, "customer":1}}
)

如果您在管道的其余部分之前运行该项目命令,则结果应该在 CET 中。

于 2013-09-17T15:43:57.813 回答
9

timezone从 3.6 开始,您可以提供日期运算符。

用您的时区替换时区。

{
  "$group":{
    "_id":{
      "year":{"$year":{"date":"$tDate","timezone":"America/Chicago"}},
      "month":{"$month":{"date":"$tDate","timezone":"America/Chicago"}},
      "dayOfMonth":{"$dayOfMonth":{"date":"$tDate","timezone":"America/Chicago"}}
    },
    "count":{"$sum":1}
  }
}
于 2018-03-20T15:17:07.140 回答
7

经过几个小时的搜索,这是对我有用的解决方案。这也很简单。只需通过减去以毫秒为单位的时区偏移量来转换时区。

25200000 = 7 小时偏移量 // 420 分钟 * 60 秒 * 1000 英里

$group: {
    _id = { 
        year: { $year : [{ $subtract: [ "$timestamp", 25200000 ]}] }, 
        month: { $month : [{ $subtract: [ "$timestamp", 25200000 ]}] }, 
        day: { $dayOfMonth : [{ $subtract: [ "$timestamp", 25200000 ]}] }
    },
    count = { 
        $sum : 1
    }
};
于 2014-11-19T19:06:04.170 回答
4

使用例如 moment.js 来确定 CET 的当前时区偏移量,但这样您就可以获得夏季和冬季偏移量

var offsetCETmillisec = moment.tz.zone('Europe/Berlin').offset(moment())* 60 * 1000;

  $group: {
    _id: {
      'year': {'$year': [{ $subtract: [ '$createdAt', offsetCETmillisec ]}] },
      'month': {'$month': [{ $subtract: [ '$createdAt', offsetCETmillisec ]}] },
      'day': {'$dayOfMonth': [{ $subtract: [ '$createdAt', offsetCETmillisec ]}] }
    },
    count: {$sum: 1}
  }
}
于 2016-09-10T08:30:57.110 回答
3

MongoDB 的文档建议您将时区偏移量与时间戳一起保存:

var now = new Date();
db.data.save( { date: now,
                offset: now.getTimezoneOffset() } );

这当然不是理想的解决方案——但它是可行的,直到我们在 MongoDb 的聚合管道中拥有一个适当的 $utcOffset 函数。

于 2016-05-25T06:47:41.430 回答
1

带时区的解决方案是一个很好的解决方案,但在 3.6 版中,您还可以使用时区格式化输出,因此,您可以得到可供使用的结果:

{
"$project":{
    "year_month_day": {"$dateToString": { "format": "%Y-%m-%d", "date": "$tDate", "timezone": "America/Chicago"}}
},
"$group":{
    "_id": "$year_month_day",
    "count":{"$sum":1}
}
}

确保你的 "$match" 也考虑时区,否则你会得到错误的结果。

于 2019-03-17T14:13:16.803 回答
0

Mongo 以 UTC 存储日期,因此这是将它们放入其他区域的过程

  • 检查 mongo 是否以 UTC 保存日期,插入一些记录等。
  • 使用 moment-timezone.js 例如 moment().tz('Europe/Zagreb').utcOffset() 函数获取指定时区的时区偏移量
  • 为 $match 阶段准备 $gte 和 $lte(例如,用户输入日期 1.1.2019 - 13.1.2019。):
    • 如果 offset 为正,则在 $match 阶段减去()那些秒;如果 offset 为负 add() 在 $match 阶段的那几秒
  • 然后将日期标准化(因为 $match 阶段将以 UTC 格式返回它们)到您的区域,如下所示: -if timezone offset is positive add() those seconds in $project stage; -如果时区偏移为负减去() $project 阶段中的那些秒。
  • $group 排在最后,这很重要(因为我们要对标准化结果进行分组,而不是 $match-ed)

基本上是这样的:将输入转换为 $match(UTC),然后标准化为您的时区。

于 2019-10-15T10:13:38.857 回答
-10
<?php
    date_default_timezone_set('Asia/Karachi');
    $date=getdate(date("U"));
    $day = $date['mday'];
    $month =$date['mon'];
    $year = $date['year'];
    $currentDate = $year.'-'.$month.'-'.$day;
?>
于 2013-09-17T14:08:37.980 回答