From fd9f36ed651a7fb75eb4af065ecd3482076169e9 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Wed, 20 Sep 2023 10:55:32 +0300 Subject: [PATCH 1/2] Customizing the isToday & isTomorrow & isYesterday functions to consider timezones --- src/libs/DateUtils.js | 52 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/src/libs/DateUtils.js b/src/libs/DateUtils.js index b33a1b1b2a73..8ec19834e790 100644 --- a/src/libs/DateUtils.js +++ b/src/libs/DateUtils.js @@ -4,11 +4,10 @@ import {es, enGB} from 'date-fns/locale'; import { formatDistanceToNow, subMinutes, + addDays, + subDays, isBefore, subMilliseconds, - isToday, - isTomorrow, - isYesterday, startOfWeek, endOfWeek, format, @@ -85,6 +84,47 @@ function getLocalDateFromDatetime(locale, datetime, currentSelectedTimezone = ti return utcToZonedTime(parsedDatetime, currentSelectedTimezone); } +/** + * Checks if a given date is today in the specified time zone. + * + * @param {Date} date - The date to compare. + * @param {String} timeZone - The time zone to consider. + * @returns {Boolean} True if the date is today; otherwise, false. + */ +function isToday(date, timeZone) { + const currentDate = new Date(); + const currentDateInTimeZone = utcToZonedTime(currentDate, timeZone); + return isSameDay(date, currentDateInTimeZone); +} + +/** + * Checks if a given date is tomorrow in the specified time zone. + * + * @param {Date} date - The date to compare. + * @param {String} timeZone - The time zone to consider. + * @returns {Boolean} True if the date is tomorrow; otherwise, false. + */ +function isTomorrow(date, timeZone) { + const currentDate = new Date(); + const tomorrow = addDays(currentDate, 1); // Get the date for tomorrow in the current time zone + const tomorrowInTimeZone = utcToZonedTime(tomorrow, timeZone); + return isSameDay(date, tomorrowInTimeZone); +} + +/** + * Checks if a given date is yesterday in the specified time zone. + * + * @param {Date} date - The date to compare. + * @param {String} timeZone - The time zone to consider. + * @returns {Boolean} True if the date is yesterday; otherwise, false. + */ +function isYesterday(date, timeZone) { + const currentDate = new Date(); + const yesterday = subDays(currentDate, 1); // Get the date for yesterday in the current time zone + const yesterdayInTimeZone = utcToZonedTime(yesterday, timeZone); + return isSameDay(date, yesterdayInTimeZone); +} + /** * Formats an ISO-formatted datetime string to local date and time string * @@ -117,13 +157,13 @@ function datetimeToCalendarTime(locale, datetime, includeTimeZone = false, curre yesterdayAt = yesterdayAt.toLowerCase(); } - if (isToday(date)) { + if (isToday(date, currentSelectedTimezone)) { return `${todayAt} ${format(date, CONST.DATE.LOCAL_TIME_FORMAT)}${tz}`; } - if (isTomorrow(date)) { + if (isTomorrow(date, currentSelectedTimezone)) { return `${tomorrowAt} ${format(date, CONST.DATE.LOCAL_TIME_FORMAT)}${tz}`; } - if (isYesterday(date)) { + if (isYesterday(date, currentSelectedTimezone)) { return `${yesterdayAt} ${format(date, CONST.DATE.LOCAL_TIME_FORMAT)}${tz}`; } if (date >= startOfCurrentWeek && date <= endOfCurrentWeek) { From 114e04737df0eef4fe6b931dbbba93c551e539c3 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Tue, 26 Sep 2023 11:14:30 +0300 Subject: [PATCH 2/2] Adding unit tests for isToday, isTomorrow and isYesterday --- src/libs/DateUtils.js | 3 +++ tests/unit/DateUtilsTest.js | 30 +++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/libs/DateUtils.js b/src/libs/DateUtils.js index 8ec19834e790..376c38c06e39 100644 --- a/src/libs/DateUtils.js +++ b/src/libs/DateUtils.js @@ -384,6 +384,9 @@ const DateUtils = { subtractMillisecondsFromDateTime, getDateStringFromISOTimestamp, getStatusUntilDate, + isToday, + isTomorrow, + isYesterday, }; export default DateUtils; diff --git a/tests/unit/DateUtilsTest.js b/tests/unit/DateUtilsTest.js index d17c1c052929..aca4b16e3823 100644 --- a/tests/unit/DateUtilsTest.js +++ b/tests/unit/DateUtilsTest.js @@ -1,5 +1,5 @@ import Onyx from 'react-native-onyx'; -import {format as tzFormat} from 'date-fns-tz'; +import {format as tzFormat, utcToZonedTime} from 'date-fns-tz'; import {addMinutes, subHours, subMinutes, subSeconds, format, setMinutes, setHours, subDays, addDays} from 'date-fns'; import CONST from '../../src/CONST'; import DateUtils from '../../src/libs/DateUtils'; @@ -130,6 +130,34 @@ describe('DateUtils', () => { expect(result).toBe(expectedDateTime); }); + describe('Date Comparison Functions', () => { + const today = new Date(); + const tomorrow = addDays(today, 1); + const yesterday = subDays(today, 1); + + const todayInTimezone = utcToZonedTime(today, timezone); + const tomorrowInTimezone = utcToZonedTime(tomorrow, timezone); + const yesterdayInTimezone = utcToZonedTime(yesterday, timezone); + + it('isToday should correctly identify today', () => { + expect(DateUtils.isToday(todayInTimezone, timezone)).toBe(true); + expect(DateUtils.isToday(tomorrowInTimezone, timezone)).toBe(false); + expect(DateUtils.isToday(yesterdayInTimezone, timezone)).toBe(false); + }); + + it('isTomorrow should correctly identify tomorrow', () => { + expect(DateUtils.isTomorrow(tomorrowInTimezone, timezone)).toBe(true); + expect(DateUtils.isTomorrow(todayInTimezone, timezone)).toBe(false); + expect(DateUtils.isTomorrow(yesterdayInTimezone, timezone)).toBe(false); + }); + + it('isYesterday should correctly identify yesterday', () => { + expect(DateUtils.isYesterday(yesterdayInTimezone, timezone)).toBe(true); + expect(DateUtils.isYesterday(todayInTimezone, timezone)).toBe(false); + expect(DateUtils.isYesterday(tomorrowInTimezone, timezone)).toBe(false); + }); + }); + describe('getDBTime', () => { it('should return the date in the format expected by the database', () => { const getDBTime = DateUtils.getDBTime();