AP Date, but UTC
eyeseast opened this issue · 6 comments
Have run into this a couple times, and running into it now: Editor puts a localized datetime in a source doc. Javascript parses as UTC and displays in local time, which is offset. Now the date is off.
Simplest solution I can think of is to parse and display as UTC, probably as a separate function, alongside apdate
.
Hey @eyeseast! Just to make sure I'm following 100% can you elaborate further on what's happening? Maybe an example of the exact input, (incorrect) output you're seeing and output you'd expect/want?
Hi! (Great library, btw.) Here's roughly what happens:
const d = new Date('2020-05-05') // editor puts this in a spreadsheet
apdate(d)
// May 4, 2020, because timezones
d.toUTCString()
// "Tue, 05 May 2020 00:00:00 GMT"
So what I'm proposing is a function alongside apdate
that does the same thing, but using getUTC*
methods. (It could also be a second argument to apdate
.)
Thanks, that helps!
This is tricky — Date
is wildly inconsistent in how it treats strings being passed to new Date
. AFAICT you actually get a UTC time-zeroed date when you do new Date('2020-05-05')
. So in that scenario, you're right — you would rather have the getUTC*()
outputs.
The original version of apdate
used to have parsing built-in, but it made it impossible for folks to have full control over how their Date objects were created. (For example, it used date-fns
v1's parse
to do this, but it'd crash and burn if someone tried to pass moment
Dates in.) So the current expectation is that any inputs have already been formatted as desired as Date objects. I am hesitant to add a variation of apdate
(and apmonth
and aptime
) that steps back from that.
We handle this by parsing any input ISO date strings with date-fns' parseISO
, and pipe that into apdate
. If you trust your inputs to be consistent you could parse that string into the right format without too much trouble (or a new dependency). This should give you what you expect no matter what time zone it runs in:
const input = '2020-05-05';
// split and coerce to numbers
const [year, month, day] = input.split('-').map(Number);
// month is zero-indexed!
const d = new Date(year, month - 1, day);
Here's more what I'm thinking, if this helps:
export default function apdateUTC(date = new Date()) {
const month = apmonthUTC(date); // assume a UTC version for now
const dayOfMonth = date.getUTCDate();
const year = date.getUTCFullYear();
return `${month} ${dayOfMonth}, ${year}`;
}
So it's the same function, but it gives you UTC instead of localized dates. (This is what I ended up doing in my own code.) I'm not worried about parsing at all here, just changing output.
Sorry, I kind of rambled there!
What I was getting at is this is happening because of a quirk of how passing a partial ISO-formatted date string into new Date
does something unexpected (gives you a local time Date at midnight UTC).
Instead of making a variation of apdate
, etc. that collaborates with that parsing quirk, I'd recommend ensuring your input Date more accurately represents what you're after - in this case, a local time Date at midnight local time, which parseISO
or that little snippet I provided above will do.
Alright, we might have to disagree on this, which is totally fine. Happy to deal with this particular collision of javascript and editors on my end. Appreciate the feedback.