How to aggregate by year-month-day on a different timezone

心已入冬 提交于 2019-11-27 00:46:25

I'm not an expert on CET and its relation to UTC, but the following code (for the shell) should do a proper conversion (adding an hour) to a MongoDB date type:

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

If you run that project command before the rest of your pipeline, the results should be in CET.

After searching for hours, this is the solution that worked for me. It is also very simple. Just convert the timezone by subtracting the timezone offset in milliseconds.

25200000 = 7 hour offset // 420 min * 60 sec * 1000 mili

$group: {
    _id = { 
        year: { $year : [{ $subtract: [ "$timestamp", 25200000 ]}] }, 
        month: { $month : [{ $subtract: [ "$timestamp", 25200000 ]}] }, 
        day: { $dayOfMonth : [{ $subtract: [ "$timestamp", 25200000 ]}] }
    },
    count = { 
        $sum : 1
    }
};

You can provide the timezone to the date operators starting in 3.6.

Replace the timezone with your timezone.

{
  "$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}
  }
}

Use for example moment.js to dertmine the current timezone offset for CET but this way you get the summer&winter offsets

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}
  }
}

MongoDB's documentation suggests that you save the timezone offset alongside the timestamp:

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

This is of course not the ideal solution – but one that works, until we have in MongoDb's aggregation pipeline a proper $utcOffset function.

The solution with timezone is a good one, but in version 3.6 you can also format the output using timezone, so, you get the result ready for use:

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

Make sure that your "$match" also considers timezone, or else you will get wrong results.

<?php
    date_default_timezone_set('Asia/Karachi');
    $date=getdate(date("U"));
    $day = $date['mday'];
    $month =$date['mon'];
    $year = $date['year'];
    $currentDate = $year.'-'.$month.'-'.$day;
?>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!