0

My question is at the bottom of this... but unfortunately, needs a long(ish) explanation:

I'm building a simple app to learn. I have a backend API (written in Hapi) and a mobile app written in Vue NativeScript.

People are to check when a task is completed. A POST request is sent to the API which marks the task as complete and assigns the time completed.

    async saveTask(payload, taskType, mongo) {
    try {
        payload.date = new Date();
        await mongo.db.collection(taskType).insertOne(payload);
        return {
            message: `Data Saved`
        };
    }
    catch (e) {
        console.log(e);
        throw e;
    }
}

As I'm using Mongo - the date is automatically saved as ISODate.

In my mobile app, I have a page that lists all the tasks and when they were completed. A Date picker allows you to view a specific day. Choosing the 10th May, I would see results for 9th May... choosing 9th of May, I would see results for 8th of May etc..

When choosing Friday 10th May 2019 -

My Date Picker returns (console logged) 'Fri May 10 2019 00:00:00 GMT+0100 (BST)'... When sending this date to the server, the server saw it as 9th May due to the +1 hour British Summer Time and returned results for 9th May.

So, to fix this I converted the date returned from my picker to an ISOString(), and sent this converted date to the server:

query.startDate = this.startDate.toISOString() returns '2019-05-09T23:00:00.000Z

On the server I log the received query.startDate and get

startDate: 2019-05-09T23:00:00.000Z

However, in order to get the tasks done for 10th May, I need to set an End Date

To do this, I leaned on Moment.js (is this overkill?)

    filters.startDate = moment(query.startDate,'YYYY-MM-DD').startOf('day').toDate();
    filters.endDate =  moment(query.startDate,'YYYY-MM-DD').endOf('day').toDate();

    const query = {
        'date' : {
            '$gte' : filters.startDate,
            '$lt' :  filters.endDate
        }
    };

Moment returns these dates:

{ startDate: 2019-05-09T23:00:00.000Z, endDate: 2019-05-10T22:59:59.999Z }

Which returns all items from the database with a date of 10th May.

My question is: is this the most efficient / sensible way to handle this. What if an Item is added at 00:00 Hours British Summer Time... (23:00 Hours UTC / GMT)... my endDate doesn't end at 23:00, it ends at 22:59... or am I confusing myself here?

When marking a task as complete, should I be setting the complete time from the local device (I'm thinking not - as new Date is set on the server, this is saved to the Mongo DB in UTC format - and I can use moment or whatever to parse that UTC client side to show the correct date?)

Sorry for the length of this - I'm just extremely confused by dates...

Rob
  • 1,576
  • 3
  • 22
  • 52
  • 3
    Yep, perfectly normal. The only correction is `$lte` rather than `$lt` otherwise you are actually missing that "last millisecond" of the **"day"** in such a range statement. To be clear an `ISODate` is actually a`BSON Date` which is again just the "milliseconds since epoch" stored with a specific flag to say "I'm a date". This of course is UTC and does not change between timezones. So *"in theory"* any date supplied as "local time" is actually converted to UTC on storage, so any "query" works on the same principle of taking "local time" input and then working via the UTC to match results. – Neil Lunn May 12 '19 at 00:31
  • 3
    The one exception comes to "aggregating data" for specific day periods. Particularly with changes in "daylight savings" time periods crossing such an aggregation, this could become "messy" with older releases of MongoDB ( i.e [Group by Date with Local Time Zone in MongoDB](https://stackoverflow.com/a/45093686/2313887) ). However this is somewhat mitigated now via [Date Expression Operators](https://docs.mongodb.com/manual/reference/operator/aggregation/#date-expression-operators) now accepting a "timezone" value which takes such things into account for you. – Neil Lunn May 12 '19 at 00:36
  • 1
    Using MomentJS may not be a overkill, it's useful library to play with Date & TimeZones. Most server applications will store date & time is UTC format, so when you send / read date to / from server, you make sure it's UTC and convert it to device timezone while showing on UI. – Manoj May 12 '19 at 06:48
  • 1
    Not really what I was saying. Even if "right now" you only think you care about the time in England ( or wherever British Summer time applies ), but some time down the track, that's probably going to change. I'm in Australia, someone else is in Uruguay, someone else in Spain and so on. But "right now" is "right now", even though each of us observe a different time of day ( or even different day ) it's still the same time in UTC. That's why you want UTC, and simply present the time to the "observer" in whatever timezone they happen to be in. – Neil Lunn May 12 '19 at 08:28
  • Thanks @NeilLunn - So using new Date() with mongo on the server stores a date in UTC format. It has been suggested to me that I also store a timezone against each user. This way, should a user log something in the UK - and move to Spain, it will still display the data to them in the UK timezone. However, what would happen if they logged something while in Spain? (the server sets the time when a task is complete). Or would it be best to just display everything in local time - regardless of where they are in the world? (the phone sets the local time) – Rob May 12 '19 at 08:29
  • So UTC is canonical. How I display it is almost irrelevant - as long as I have it in UTC, I cam present it to the user in whatever timezone they like. Thanks for this! Dates are mind bending – Rob May 12 '19 at 08:32
  • 1
    This is why we used to say on mailing list groups to never "top post". You removed your last comment because you wanted to say more, but my comment now preceding your last comment is in response to that comment. Just to keep the context. You're missing the point. No need to **store** a timezone. Just take that information from the current **"observer"**. Sending a UTC value to the client for example does just that. It's the same milliseconds since epoch everywhere on the globe – Neil Lunn May 12 '19 at 08:32

0 Answers0