I try to replace momentjs with date-fns
but I am struggling with a very simple thing: I need to calculate startOfDay, end of day and addDays for the dates that I have got in timestamps and according to the giving timezone.
date = 1492437600; // Monday April 17, 2017 12:00:00 (pm) in time zone America/Noronha
timeZone = 'America/Noronha';
_startOfDay = utcToZonedTime(startOfDay(date*1000), timeZone).getTime()/1000;
and I have got the result for the _startOfDay = 1492365600 that is Sunday April 16, 2017 16:00:00 (pm) in time zone America/Noronha
What I am doing wrong? thanks in advance
Note: See the bottom of this answer for the best solution
Old Answer:
I see this question is 11 months old (as of writing) but thought I'd answer it as I hit the same problem, and others may come here in the future with the same question.
The date-fns library doesn't have timezone support, so you need to also use the date-fns-tz library. Import the getTimezoneOffset function from date-fns-tz and use to calculate the offset between the local (browser) timezone and the timezone you wish to calculate end of day for (i.e. America/Noronha). Note that the date-fns "endOf" functions use the local/browser timezone.
E.g.
import { endOfDay } from 'date-fns';
import { getTimezoneOffset } from 'date-fns-tz/esm';
const MILLISECS_IN_DAY = 86400000;
const localTz = Intl.DateTimeFormat().resolvedOptions().timeZone; // Browser Timezone
const tzOffset = getTimezoneOffset('America/Noronha') - getTimezoneOffset(localTz);
// Have to cater for negative offsets
const tzOffsetEOD = (tzOffset < 0) ? (MILLISECS_IN_DAY + tzOffset) : tzOffset;
let testDate = new Date();
let eodInTimezone = endOfDay(testDate).getTime() - tzOffsetEOD; // in millisecs
// Have to project forward a day if the result is in the past
if (eodInTimezone < testDate.getTime()) eodInTimezone += MILLISECS_IN_DAY;
Someone may be able to come up with a more elegant solution to this problem. If I do I'll post back here.
New Answer:
This solution works best for all "End Of" date-fns functions:
import { endOfDay, endOfWeek, endOfMonth, endOfYear } from 'date-fns';
import { utcToZonedTime, zonedTimeToUtc } from 'date-fns-tz/esm';
const calcZonedDate = (date, tz, fn, options = null) => {
const inputZoned = utcToZonedTime(date, tz);
const fnZoned = (options) ? fn(inputZoned, options) : fn(inputZoned);
return zonedTimeToUtc(fnZoned, tz);
}
const getZonedEndOfDay = (date, timeZone) => {
return calcZonedDate(date, timeZone, endOfDay);
}
const getZonedEndOfWeek = (date, timeZone) => {
return calcZonedDate(date, timeZone, endOfWeek, { weekStartsOn: 1 });
}
const getZonedEndOfMonth = (date, timeZone) => {
return calcZonedDate(date, timeZone, endOfMonth);
}
const getZonedEndOfYear = (date, timeZone) => {
return calcZonedDate(date, timeZone, endOfYear);
}
// Example Usage
let endOfDayZoned = getZonedEndOfDay(new Date(), 'America/Noronha');
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With