How to calculate the first timestamp/Date of a specific day and the last second's timestamp?

65 Views Asked by At

I have a given date as Date-object in JavaScript.

From that particular date (e.g. 2024-16-01, 22:35), I want to go to the beginning of the day (2024-16-01, 00:00) and the end of the day (2024-16-01, 23:59).

I tried the library date-fns, but this gives wrong values.

import { addDays, addHours, endOfDay, startOfDay, subHours } from 'date-fns';

// d = new Date(...)
const startDate = subHours(startOfDay(d), hoursBefore);
const endDate = addHours(endOfDay(d), hoursAfter);

console.log('Date: ', d);
console.log('Start Of Day: ', startOfDay(d));
console.log('End Of Day: ', endOfDay(d));
console.log('startDate: ', startDate);
console.log('endDate: ', endDate);

Output:

Date:  2024-01-16T17:00:00.000Z
Start Of Day:  2024-01-16T17:00:00.000Z
End Of Day:  2024-01-17T16:59:59.999Z
startDate:  2024-01-16T05:00:00.000Z
endDate:  2024-01-17T21:59:59.999Z

As one can see, the values are totally different from what they actually should be. Is the timezone playing a disturbing role here? If so, how can I mitigate such risks of getting wrong values?

Or is there another approach how to deal with that?

2

There are 2 best solutions below

3
0stone0 On BEST ANSWER

startOfDay already returns:

The start of a day

So there is no need to combine it with subHours or addHours, just do startOfDay(d):

const d = new Date();

const startDate = dateFns.startOfDay(d);
const endDate = dateFns.endOfDay(d);

console.log('Date: ', d);
console.log('Start Of Day: ', startDate);
console.log('End Of Day: ', endDate);
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.28.5/date_fns.min.js"></script>


Regarding the time-zone, you'll need date-fns-tz to convert it relative to your current zone / utc, please refer to:

0
Peter Seliger On

Take any passed Date object or its parsable string-representation and ...

  • create a new Date instance and assign it to e.g. a begins constant.
  • set each of the begins date's values (hours, minutes, milli/seconds) to zero.
  • add the 24 hours equivalent of milliseconds minus one millisecond to the millisecond of the already computed begins date.
  • create a new Date instance from the computed milliseconds and assign it to e.g. an ends constant.

function getDayDataRange(dateOrString) {
  const begins = new Date(
    dateOrString?.getTime?.() ?? String(dateOrString)
  );
  begins.setHours(0);
  begins.setMinutes(0);
  begins.setSeconds(0);
  begins.setMilliseconds(0);

  // - add the 24 hours equivalent of milliseconds minus
  //   one millisecond to the millisecond of the already
  //   computed `begins` date
  // - create a new `Date` instance from the computed milliseconds.

//const ends = new Date(begins.getTime() + (24 * 60 * 60 * 1000) - 1)
  const ends = new Date(begins.getTime() + 86400000 - 1);

  return { begins, ends };
}

const { begins, ends } = getDayDataRange("2024-01-16T17:30:59.000Z");

console.log('... work around the SO-specific console-logging ...');
console.log({
  // - Stack Snippets have their own console implementation.
  // - Thus, one needs to (locally) stringify the date objects
  //   before SO console-logging forces an ISO string conversion.
  begins: String(begins),
  ends: String(ends),
});

console.log('... standard console-logging which does work outside of SO ...');
console.log(
  getDayDataRange(new Date)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }