I’ve run into a mysterious issue today - and before I start working on my conspiracy theories, I’d first like to check whether I’m just being a little stupid…
I have an agenda app that allows recurrent appointments. When I test it on localhost (either with Minimongo or with my live MongoDB), everything works perfectly. However, when I test it with the live server (Heroku), my appointments end up in the wrong days! The same action, with the same days, leading to different results.
I’ve already pushed my latest updates to Heroku, so it shouldn’t be an issue of code differences…
Thanks for the reply. That shouldn’t be the issue… Because the appointment time (HH:mm) is always correct - it’s the day that ends up wrong. When using the live server, appointments always land one day earlier than expected (if set for Tuesday, it ends up on Monday).
I owe you an apology. You pointed me to the right direction.
The problem was my handling of timezones… it was messing things up.
Instead of keeping times and performing calculations with days, I was using functions like startOf(‘month’), which have implications on both.
MomentJS behavior can be inconsistent across clients/servers regarding timezone.
The best thing to do is either contemplate timezones as part of your app’s logic (instead of leaving it for moment to handle automatically), or in case your app’s users are all in the same timezone, redefine your server’s timezone to that one.
In Heroku, you just have to go to the Config Variables and add:
Name
TZ
Value
(whatever timezone you wish) Americas/Sao_Paulo
Rather than change the timezone on the server (which you’ll have to remember to do everytime you spin up a new server), I prefer to develop locally with meteor running in the UTC timezone:
TZ=UTC meteor
This replicates the environment of most cloud servers so that issues like this can be reproduced and fixed locally.
This makes indeed sense if you app will run in multiple timezones. Maybe even set it to something very wrong for you, so that you notice that you need to use moment-timezone or so if you use startOf or endOf.
On the other hand, if you have one timezone, i would set this timezone on the process with environment-vars (TZ=xxxx) . Most cloud service or systems like kubernetes support environment variables.
Even if you’re sure all your users are in one timezone, you still need to cater for:
Daylight Savings Time - the client timezone will shift relative to the server.
Users using the app while travelling in a different timezone.
Whenever I have methods which rely on the client’s local time, I always send new Date().getTimezoneOffset() as a method parameter, then it’s trivial for the server to calculate the client’s local time by subtracting the timeZoneOffset from it’s own UTC.
Personally I don’t like using moment.js either. Date/time manipulation is so trivial I prefer to do it myself (using just a few of my own additional Date prototypes).