Подтвердить что ты не робот

Как агрегировать по году-месяцу в другой часовой пояс

У меня есть 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", это другой день.

4b9b3361

Ответ 1

Я не эксперт по CET и его отношение к UTC, но следующий код (для оболочки) должен сделать правильное преобразование (добавление часа) в тип даты MongoDB:

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

Если вы запустите эту команду проекта до остальной части вашего конвейера, результаты должны быть в CET.

Ответ 2

После поиска часов это решение, которое сработало для меня. Это тоже очень просто. Просто преобразуйте часовой пояс, вычитая смещение часового пояса в миллисекундах.

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

Ответ 3

Вы можете предоставить 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}
  }
}

Ответ 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}
  }
}

Ответ 5

Документация MongoDB предлагает, что вы сохраняете смещение часового пояса наряду со меткой времени:

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

Это, конечно, не идеальное решение, но работающее, пока в конвейере агрегации MongoDb не будет создана правильная функция $utcOffset.

Ответ 6

Хорошее решение с часовым поясом, но в версии 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" также учитывает часовой пояс, иначе вы получите неправильные результаты.

Ответ 7

Монго хранит даты в UTC, так что это процедура, чтобы получить их в другой зоне

  • проверьте, что Mongo сохраняет даты в UTC, вставьте несколько записей и т.д.
  • получить смещение часового пояса с помощью функции moment-timezone.js, например функции moment(). tz ('Europe/Zagreb'). utcOffset(), для вашего указанный часовой пояс
  • Подготовьте $ gte и $ lte для этапа $ match (например, ввод данных пользователем для дат 1.1.2019 - 13.1.2019.):
    • Если смещение положительное, subtract() эти секунды на этапе $ match; Если смещение отрицательно, добавьте() эти секунды на этапе $ match
  • Затем нормализуйте даты (потому что $ match stage вернет их в UTC) в вашу зону следующим образом: -if смещение часового пояса является положительным add() в эти секунды на этапе $ project; -if Смещение часового пояса является отрицательным subtract() в эти секунды на этапе $ project.
  • $ group идет последним, это важно (потому что мы хотим сгруппировать нормализованные результаты, а не $ match-ed)

В основном это так: сдвиньте ввод в $ match (UTC), а затем нормализуйте в соответствии с вашим часовым поясом.

Ответ 8

<?php
    date_default_timezone_set('Asia/Karachi');
    $date=getdate(date("U"));
    $day = $date['mday'];
    $month =$date['mon'];
    $year = $date['year'];
    $currentDate = $year.'-'.$month.'-'.$day;
?>