Search code examples
javascriptreact-nativedatetimezonedate-fns

Compare two UTC dates with date-fns


I'm trying to compare two dates in UTC format with date-fns, but I'm not getting it. The two values ​​look the same, but the isEquals() function returns false for comparison.

The purpose of the code below is to search for the schedules that are marked and check if they fit the times of the array range, if there is a compatible schedule, it returns the object by inserting it in the constant date

import React, { useState, useEffect } from 'react';
import { utcToZonedTime } from 'date-fns-tz';
import {
  format,
  setHours,
  setMinutes,
  setSeconds,
  isBefore,
  isEqual,
  parseISO,
} from 'date-fns';
import enUS from 'date-fns/locale/en-US';

import api from '~/services/api';

const range = [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];

export default function Dashboard() {
  const [date, setDate] = useState(new Date());

  useEffect(() => {
    async function loadSchedule() {
      const response = await api.get('schedule', {
        params: { date },
      });

      const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;

      const data = range.map((hour) => {
        const checkDate = setSeconds(setMinutes(setHours(date, hour), 0), 0);
        const compareDate = utcToZonedTime(checkDate, timezone);

        return {
          time: `${hour}:00h`,
          past: isBefore(compareDate, new Date()),
          appointment: response.data.find((appoint) =>
            isEqual(parseISO(appoint.date), compareDate)
          ),
        };
      });

      setSchedule(data);
    }

    loadSchedule();
  }, [date]);

}

I made a test code to print the results on the Reactotron and below are the printed values:

console.tron.log(`${isEqual(parseISO(response.data[1].date), 
                   compareDate)}\n
                   ${parseISO(response.data[1].date)}\n${compareDate}`);

Result:

false
Wed Jun 10 2020 19:00:00 GMT-0300 (Brasilia Standard Time)
Wed Jun 10 2020 19:00:00 GMT-0300 (Brasilia Standard Time)

Actual values ​​for each of the dates:

console.tron.log(`${response.data[1].date}\n${compareDate}`);
2020-06-10T22:00:00.000Z
Wed Jun 10 2020 20:00:00 GMT-0300 (Brasilia Standard Time)

But if I print only the value of the compareDate variable, it changes the format:

console.tron.log(compareDate);
2020-06-10T21:00:00.002Z

Solution

  • date-fns's isEqual() function also takes into consideration the milliseconds value, as questioned in the comments.

    This information can also be found on date-fns isEqual() docs, in the example:

    // Are 2 July 2014 06:30:45.000 and 2 July 2014 06:30:45.500 equal?
    
    var result = isEqual(
      new Date(2014, 6, 2, 6, 30, 45, 0),
      new Date(2014, 6, 2, 6, 30, 45, 500)
    )
    // it returns false`
    

    You should import setMilliseconds() from date-fns and also use it in the line where you set checkDate value.