skip to Main Content

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

Answers


  1. 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:

    Login or Signup to reply.
  2. 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; }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search