How to disregard timezone using Moment.js? - date

I've lost track of how many questions & responses I've read while trying to find an answer on this. The ones that sound like they're related often aren't, or else the users are just accused of being confused. (As an example, the first answer here just tells the person asking the question that they don't really mean to be asking what they're asking. Then there's this one. The most upvoted answer here says it's just impossible. Etc., etc., etc.)
I need to be able to take a time--say 9:00 AM--and work with it as 9:00 AM regardless of which timezone my user is in. If a user pulls up this time in a US/Eastern timezone, they should see this value as 9:00 AM. If a user pulls up this time in a US/Pacific timezone, they should see this value as 9:00 AM. I recognize that this is not actually the same moment in time, and I don't need it to be.
To illustrate, let's call the timezone-immune timestamp I'm talking about timezoneImmuneTimestamp, and say that its value should always be 9:00 AM.
Say I'm executing someMomentInUsEasternTimezone.diff(timezoneImmuneTimestamp, 'minutes'), where someMomentInUsEasternTimezone is equal to 10:00AM (EST). The answer I need is 60 minutes.
Now let's add another Moment, someMomentInUsPacificTimezone and say its value is 11:00AM (PST). When I execute someMomentInUsWesternTimezone.diff(timezoneImmuneTimestamp, 'minutes'), the answer I need is 120 minutes.
Has anyone else had this particular problem, and more importantly, solved it?

It sounds like you want to work with only the "wall time" of each moment object. To do that, first create a clone of each moment and set their offsets to zero, as if they were UTC. When doing so, pass true to keep the wall time instead of the same point in actual universal time.
This is described in the docs for the utcOffset function:
The utcOffset function has an optional second parameter which accepts
a boolean value indicating whether to keep the existing time of day.
Passing false (the default) will keep the same instant in Universal Time, but the local time will change.
Passing true will keep the same local time, but at the expense of choosing a different point in Universal Time.
Thus, to get the difference in minutes between momentA and momentB with respect only to wall time:
momentA.clone().utcOffset(0, true).diff(momentB.clone().utcOffset(0, true), 'minutes')
Though missing from the docs, the same argument can be passed to the utc function. So if you prefer, you can shorten it to:
momentA.clone().utc(true).diff(momentB.clone().utc(true), 'minutes')
(Cloning helps the rest of your code by not mutating the original moment objects.)
Also - The Moment team highly recommends only using Moment in legacy/existing code. If you are writing a new application, please try Luxon instead. In Luxon, the setZone function has a keepLocalTime option that does the same thing as I showed in Moment.

Related

Handling dates without a time component

Some events don't take place at any specific time and instead are meant to be valid for the whole day irrespective of the time zone the user is at.
For the sake of argument, let's say a system sitting on a server (up in the cloud) runs a job at 5 am and imports data from a different system between this run and the last (24 hours ago). The actual user sitting at his desk doesn't know when the job runs, the user only knows that they go to sleep at night, the server crunches all the entries for the day.
The next morning the user wants to see all the entries from yesterday (what ever the job produced) and they go to the app, pull up a calendar input selector and they pick the 5/26/2022 (today being 5/27/2022).
Assuming the developers followed best practices, the client will transform the date into it's UTC version and send it up through an API. Chances are, depending on where the user is located and the server is, there might be a mismatch.
I could send the date up without it being UTC or I could send a UTC date and try to adjust it back to local time so that I could then compare with the date on record (that exists without an actual time zone).
What I am asking is:
What's the more conventional answer to this particular problem?
Is the idea of a date without time or time zone just ridiculous?
Use UNIX Time. It will give you a timestamp that is universal no matter what timezone the user is in. You can then convert it into whatever timezone you want to.
The concern you describe is well solved/addressed by the ISO 8601 dates/time presentation protocol.
All modern software can read/write dates in ISO 8601.
In Unix machines, the correct command is date with option -I
-I[FMT], --iso-8601[=FMT]
output date/time in ISO 8601 format. FMT='date' for date
only (the default), 'hours', 'minutes', 'seconds', or 'ns'
for date and time to the indicated precision. Example:
2006-08-14T02:34:56-06:00

AlphaVantage: Random data in downloaded adjusted time series

I download adjusted time series from AlphaVantage using the following call (you need to insert your own API key):
https://www.alphavantage.co/query?function=TIME_SERIES_daily_adjusted&symbol=^GDAXI&outputsize=full&apikey=yourAPIkey
Next, I look at one particular (and faulty) data point at date 2003-04-18:
"5. adjusted close": "766464.0000"
Then, I reload the exact same API call and check the same data point again. However, this time there is a different value for adjusted close here! Every time I reload, different value (and always wrong, too). Why is this happening and how do I fix this wrong data?
For those who come across the same problem with AlphaVantage data, I try to answer my own question.
The random data problem only occurs on some (not all) non-trading days. For example, the above date is Good Friday in 2003. I have written a function to filter out all non-trading days from the downloaded AlphaVantage data, and that "fixed" the problem of the random-data days.

Change the hour when org-mode is starting new day

I use org-mode to clock my work and sometimes I work past midnight for few hours.
So, for example, I clocked time starting 03.06.2013 10pm and ending 04.06.2013 2am.
And org-mode is dividing it at 0am, starting new day. But it would be more convinient for me if that time 0am-2am was recorded for 03.06.2013 instead of 04.06.2013.
So I want to be able to specify at what time (say, 4am) org-mode is deciding the new day has started.
I can use a workaround by shifting timezone for the emacs process, but then I need to keep in mind that all recorded time is shifted... Not very convinient.
See the variable org-extend-today-until, a variable defined in org.el.
Documentation:
The hour when your day really ends. Must be an integer.
This has influence for the following applications:
When switching the agenda to "today". It it is still earlier than
the time given here, the day recognized as TODAY is actually yesterday.
When a date is read from the user and it is still before the time given
here, the current date and time will be assumed to be yesterday, 23:59.
Also, timestamps inserted in capture templates follow this rule.

passing timezone from client (GWT) to server (Joda Time)

I'm using GWT on the client (browser) and Joda Time on the server. I'd like to perform some DB lookups bounded by the day (i.e. 00:00:00 until 23:59:59) that a request comes in, with the time boundaries based on the user's (i.e. browser) timezone.
So I have the GWT code do a new java.util.Date() to get the time of the request, and send that to the server. Then I use Joda Time like so:
new DateTime(clientDate).toDateMidnight().toDateTime()
The trouble of course is that toDateMidnight(), in the absence of a specified TimeZone, will use the system's (i.e. the server's) TimeZone. I've been trying to find a simple way to pass the TimeZone from the browser to the server without much luck. In GWT I can get the GMT offset with:
DateTimeFormat.getFormat("Z").fmt(new Date())
which results in something like "-0400". But Joda Time's DateTimeZone.forID() wants strings formatted like "America/New_York", or an integer argument of hours and minutes. Of course I can parse "-0400" into -4 hours and 0 minutes, but I'm wondering if there is not a more straightforward way of doing this.
You could use java.util.Date's getTimezoneOffset() method. It's deprecated, but that's pretty usual for Date handling in GWT currently.
And AFAIR, you can specify something similar to "UTC+4" in Joda time.
Update: I looked it up, and it's "+04:00". Or use DateTimeZone.forOffsetHours() or even forOffsetMillis().
Gwittir (http://www.gwtsite.com) is a library for GWT that includes many cool utilities, like databinding, animation, reflection, and more. However, there are some other interesting goodies as well like the new Joda Time integration. If you have ever been frustrated by GWT’s lack of java.util.Calendar support, you’ll love this, as it makes it easy to do date manipulations in your applications.
otherwise, there are other ways to get timezone offset with + & -.
import java.util.TimeZone;
use: TimeZone.getDefault().getRawOffset()
this function will return the offset time in millisecond about your phone seeting. For Example, GMT-04:00 is equals to (-4)*60*60*1000 = -14400000.
After some operations to get the number which you want.
I have a similar but slightly different problem I think.
I actually need to store the clients timezone on the server, so that I can send out messages about dates stored in their calendar.
The dates are stored in UTC time in google app engine and of course I can store the current Timezone offset when creating the appointment. The problem comes when for instance I want to send out a summary email with a list of upcoming appointments in it. These appointments need to be offset with the correct Timezone adjustments for the client (Im happy to assume that they are still in the same timezone as when they created the appointment).
The real problem comes with Daylight Savings adjustments, so for instance I might have appointments stored for Saturday 30th October 2010 at 1pm (BST[GMT+60]) and Monday 1st November 2010 at 1pm (GMT).
So as you can imagine, I cant just use the current timezone offset (BST) as that would mean that the appointment on Monday 1st November would be listed as 2pm rather than 1pm (GMT+60)
It occurs to me that the best way to deal with this is just to store the timezone offset with each appointment individually, but I feel it would be much better to be able to determine the original timezone correctly in the first place, then just let java do the correct adjustments.

Should the timezone be a constant or a variable?

I have a few places in the code where I need to use the TimeZone. I can get the timezone name using DateTime::TimeZone. Is it reasonable to put the timezone name in a constant? Or should it be in a variable?
If the value can change, use a variable, of it is guaranteed to stay the same, use a constant.
For a timezone, the chance it will change is not big, but it is also not 0. The user can change the timezone and it would be nice if the program behaves accordingly.
I vote for variable. You could end up with different users in different timezones working with your application, even if you doubt that could ever happen. It happened to me a couple of years ago.
Look at where the timezone is coming from. Is it the timezone of a city? Make it constant. Is it the timezone of the user? Make it variable - we users travel all the time, and we reset the timezone on our laptops so that Outlook scheduling will work correctly at the new location.