получить общее время онлайн между 2 датами - PullRequest
0 голосов
/ 25 марта 2020

У меня есть следующая коллекция:

[
  { "_id" : ObjectId("5e7b38534512e95591e14c59"), "name" : "Luna", "online" : true },
  { "_id" : ObjectId("5e7b386b4512e95591e14c5a"), "name" : "Luna", "online" : false },
  { "_id" : ObjectId("5e7b386b4512e95591e14c5b"), "name" : "Luna", "online" : true },
  { "_id" : ObjectId("5e7b4e128e6bf5694924db09"), "name" : "Luna", "online" : false },
  { "_id" : ObjectId("5e7b4ec81b36e86a1fb754bf"), "name" : "Luna", "online" : true },
  { "_id" : ObjectId("5e7b4f3b1b36e86a1fb754c0"), "name" : "Luna", "online" : false },
  { "_id" : ObjectId("5e7b4f581b36e86a1fb754c1"), "name" : "Luna", "online" : true },
  { "_id" : ObjectId("5e7b5065f5700f6bee612040"), "name" : "Luna", "online" : false },
  { "_id" : ObjectId("5e7b51a3f5700f6bee612041"), "name" : "Luna", "online" : true },
  { "_id" : ObjectId("5e7b5885f5700f6bee612042"), "name" : "Luna", "online" : false },
  { "_id" : ObjectId("5e7b588ff5700f6bee612043"), "name" : "Luna", "online" : true }
]

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

Теперь я уже нашел способ запроса данных между двумя датами:

var objectIdFromDate = function (date) {
    if(typeof date === 'string') date = new Date(date);
    return ObjectId( Math.floor(date.getTime() / 1000).toString(16) + "0000000000000000" );
};

db.getCollection('timeline').aggregate([
    {$match:{
        name:"Luna",
        _id:{
               $gte: objectIdFromDate("2020-03-25T10:54:35.000Z"),
               $lt: objectIdFromDate("2020-03-25T12:36:53.000Z") 
            }
    }},
    // ... ??? ...
])

Я не могу понять, как подсчитать общее количество время в сети между состоянием в сети (true = вход в систему, false = выход из системы) Документ, который я хотел бы получить, выглядел бы примерно так:

{
  name:"Luna",
  totalTimeOnline:<datetime here>
}

1 Ответ

0 голосов
/ 25 марта 2020

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

Отображаемое время отображается в формате ЧЧ: ММ: СС, а длительности указаны в миллисекундах.

Если вы заметили, мои временные интервалы основаны на последовательности Фибоначчи, за исключением 01:00 и 01:30, потому что мне нужно было различать их.

Когда текущий вход в систему ОНЛАЙН, с тех пор пользователь находится в автономном режиме.

const main = () => {
  let sessions = calculateSessions(logins);

  Object.keys(sessions).forEach((key) => {
    let duration = sessions[key].reduce((sum, ms) => sum + ms);
    console.log(`Time spent ${key}: ${formatTime(duration)}`);
  });
}

let logins = [
 { "id" :  1, "timestamp" : "2020-03-23T00:00:00.000Z", "online" : true  },
 { "id" :  2, "timestamp" : "2020-03-23T01:00:00.000Z", "online" : false },
 { "id" :  3, "timestamp" : "2020-03-23T01:30:00.000Z", "online" : true  },
 { "id" :  4, "timestamp" : "2020-03-23T02:00:00.000Z", "online" : false },
 { "id" :  5, "timestamp" : "2020-03-23T03:00:00.000Z", "online" : true  },
 { "id" :  6, "timestamp" : "2020-03-23T05:00:00.000Z", "online" : false },
 { "id" :  7, "timestamp" : "2020-03-23T08:00:00.000Z", "online" : true  },
 { "id" :  9, "timestamp" : "2020-03-23T13:00:00.000Z", "online" : false },
 { "id" : 10, "timestamp" : "2020-03-23T21:00:00.000Z", "online" : true  },
 { "id" : 12, "timestamp" : "2020-03-24T10:00:00.000Z", "online" : false },
 { "id" : 13, "timestamp" : "2020-03-25T07:00:00.000Z", "online" : true  }
];

// Assuming dates are pre-sorted and the online status is always staggered
const calculateSessions = (logins) => {
  return logins.reduce((sessions, login, index, all) => {
    if (index > 0) {
      let duration = new Date(login.timestamp) - new Date(all[index - 1].timestamp);
      sessions[login.online ? 'offline' : 'online'].push(duration);
    }
    return sessions;
  }, { online : [], offline : [] });
};

const formatTime = (ms) => {
  const pad = (n, z = 2) => ('00' + n).slice(-z);
  const hh = pad(ms / 3.6e6 | 0);
  const mm = pad((ms % 3.6e6) / 6e4 | 0);
  const ss = pad((ms % 6e4) / 1000 | 0);
  const mmm = pad(ms % 1000, 3);
  return `${hh}:${mm}:${ss}.${mmm}`;
};

main();
.as-console-wrapper { top: 0; max-height: 100% !important; }

Specifi c сценарий использования

const main = () => {
  let details = calculateTimeOnline('Luna', logins);

  console.log(Object.assign({}, details, {
    totalTimeOnline : formatTime(details.totalTimeOnline)
  }));
}

let logins = [
 { "id" :  1, "timestamp" : "2020-03-23T00:00:00.000Z", "online" : true  },
 { "id" :  2, "timestamp" : "2020-03-23T01:00:00.000Z", "online" : false },
 { "id" :  3, "timestamp" : "2020-03-23T01:30:00.000Z", "online" : true  },
 { "id" :  4, "timestamp" : "2020-03-23T02:00:00.000Z", "online" : false },
 { "id" :  5, "timestamp" : "2020-03-23T03:00:00.000Z", "online" : true  },
 { "id" :  6, "timestamp" : "2020-03-23T05:00:00.000Z", "online" : false },
 { "id" :  7, "timestamp" : "2020-03-23T08:00:00.000Z", "online" : true  },
 { "id" :  9, "timestamp" : "2020-03-23T13:00:00.000Z", "online" : false },
 { "id" : 10, "timestamp" : "2020-03-23T21:00:00.000Z", "online" : true  },
 { "id" : 12, "timestamp" : "2020-03-24T10:00:00.000Z", "online" : false },
 { "id" : 13, "timestamp" : "2020-03-25T07:00:00.000Z", "online" : true  }
];

// Assuming dates are pre-sorted and the online status is always staggered
const calculateTimeOnline = (user, logins) => {
  return logins.reduce((result, login, index, all) => {
    return index > 0 && !login.online
      ? Object.assign(result, {
          totalTimeOnline : result.totalTimeOnline +
            new Date(login.timestamp).getTime() -
            new Date(all[index - 1].timestamp).getTime()
        })
      : result;
  }, {
    name: user,
    totalTimeOnline: 0
  });
};

const formatTime = (ms) => {
  const pad = (n, z = 2) => ('00' + n).slice(-z);
  const hh = pad(ms / 3.6e6 | 0);
  const mm = pad((ms % 3.6e6) / 6e4 | 0);
  const ss = pad((ms % 6e4) / 1000 | 0);
  const mmm = pad(ms % 1000, 3);
  return `${hh}:${mm}:${ss}.${mmm}`;
};

main();
.as-console-wrapper { top: 0; max-height: 100% !important; }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...