Skip to content

Commit

Permalink
Create function to check wether a date corresponds to day
Browse files Browse the repository at this point in the history
  • Loading branch information
mgonzalezg9 committed May 28, 2024
1 parent af4c880 commit b08ac01
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 64 deletions.
2 changes: 1 addition & 1 deletion src/weather/services/weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
Weather,
WeatherResponse,
} from "../interfaces";
import { formatMilliseconds } from "../utils/time-formatter";
import { formatMilliseconds } from "../utils/time";

const FORECAST_MAX_HOURS = 10;
const UNIT_SYSTEM = "metric";
Expand Down
95 changes: 95 additions & 0 deletions src/weather/utils/__tests__/data/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
const MINUTE = 60000;
const HOUR = MINUTE * 60;

export const ES_LOCALE_TEST_SUITE = [
[0, "00:00"],
[MINUTE, "00:01"],
[2 * MINUTE, "00:02"],
[HOUR, "01:00"],
[2 * HOUR, "02:00"],
[12 * HOUR, "12:00"],
[13 * HOUR, "13:00"],
[23 * HOUR, "23:00"],
[24 * HOUR, "00:00"],
] as const;
export const EN_LOCALE_TEST_SUITE = [
[0, "12:00 AM"],
[MINUTE, "12:01 AM"],
[2 * MINUTE, "12:02 AM"],
[HOUR, "01:00 AM"],
[2 * HOUR, "02:00 AM"],
[12 * HOUR, "12:00 PM"],
[13 * HOUR, "01:00 PM"],
[23 * HOUR, "11:00 PM"],
[24 * HOUR, "12:00 AM"],
] as const;

export const IS_DAY_TEST_SUITE = [
{
time: new Date(Date.UTC(2022, 1, 1, 0, 0, 0)), // 00:00
sunrise: new Date(Date.UTC(2022, 1, 1, 6, 0, 0)), // 06:00
sunset: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
result: false,
},
{
time: new Date(Date.UTC(2022, 1, 1, 12, 0, 0)), // 12:00
sunrise: new Date(Date.UTC(2022, 1, 1, 6, 0, 0)), // 06:00
sunset: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
result: true,
},
{
time: new Date(Date.UTC(2022, 1, 1, 23, 59, 59)), // 23:59
sunrise: new Date(Date.UTC(2022, 1, 1, 6, 0, 0)), // 06:00
sunset: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
result: false,
},
{
time: new Date(Date.UTC(2022, 1, 2, 0, 0, 0)), // 00:00
sunrise: new Date(Date.UTC(2022, 1, 1, 6, 0, 0)), // 06:00
sunset: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
result: false,
},
{
time: new Date(Date.UTC(2022, 1, 1, 5, 59, 59)), // 05:59
sunrise: new Date(Date.UTC(2022, 1, 1, 6, 0, 0)), // 06:00
sunset: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
result: false,
},
{
time: new Date(Date.UTC(2022, 1, 1, 18, 0, 1)), // 18:00
sunrise: new Date(Date.UTC(2022, 1, 1, 6, 0, 0)), // 06:00
sunset: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
result: false,
},
{
time: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
sunrise: new Date(Date.UTC(2022, 1, 1, 6, 0, 0)), // 06:00
sunset: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
result: true,
},
{
time: new Date(Date.UTC(2022, 1, 1, 5, 0, 0)), // 05:00
sunrise: new Date(Date.UTC(2022, 1, 1, 6, 0, 0)), // 06:00
sunset: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
result: false,
},
{
time: new Date(Date.UTC(2022, 1, 1, 19, 0, 0)), // 19:00
sunrise: new Date(Date.UTC(2022, 1, 1, 6, 0, 0)), // 06:00
sunset: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
result: false,
},
// Different year dates
{
time: new Date(Date.UTC(2023, 1, 1, 12, 0, 0)), // 12:00
sunrise: new Date(Date.UTC(2022, 1, 1, 6, 0, 0)), // 06:00
sunset: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
result: true,
},
{
time: new Date(Date.UTC(2023, 1, 1, 0, 0, 0)), // 0:00
sunrise: new Date(Date.UTC(2022, 1, 1, 6, 0, 0)), // 06:00
sunset: new Date(Date.UTC(2022, 1, 1, 18, 0, 0)), // 18:00
result: false,
},
] as const;
45 changes: 0 additions & 45 deletions src/weather/utils/__tests__/time-formatter.spec.ts

This file was deleted.

40 changes: 40 additions & 0 deletions src/weather/utils/__tests__/time.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { formatMilliseconds, isDayTime } from "../time";
import {
EN_LOCALE_TEST_SUITE,
ES_LOCALE_TEST_SUITE,
IS_DAY_TEST_SUITE,
} from "./data";

describe("Weather Service Time formatter", () => {
const esLocale = "es-ES";
it.each(ES_LOCALE_TEST_SUITE)(
`should format time for ${esLocale}`,
(time, result) => {
expect(formatMilliseconds({ time, locale: esLocale })).toBe(result);
}
);

const enLocale = "en-US";
it.each(EN_LOCALE_TEST_SUITE)(
`should format time for ${enLocale}`,
(time, result) => {
expect(formatMilliseconds({ time, locale: enLocale })).toBe(result);
}
);

IS_DAY_TEST_SUITE.forEach(({ time, sunrise, sunset, result }) => {
it(`should correctly determine if it is day time for ${formatMilliseconds({
time: time.getTime(),
locale: enLocale,
timeZone: "UTC",
})}`, () => {
expect(
isDayTime({
time,
sunrise,
sunset,
})
).toBe(result);
});
});
});
18 changes: 0 additions & 18 deletions src/weather/utils/time-formatter.ts

This file was deleted.

70 changes: 70 additions & 0 deletions src/weather/utils/time.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
interface formatMillisecondsOptions {
time: number;
locale: string;
timeZone?: string;
}

/**
* Formats a given time in milliseconds to a localized time string.
*
* @param {Object} options - The options object.
* @param {number} options.time - The time in milliseconds since the Unix epoch (January 1, 1970 00:00:00 UTC).
* @param {string} options.locale - A string with a BCP 47 language tag, or an array of such strings, to specify the locale.
* @param {string} [options.timeZone="UTC"] - An optional string representing the time zone to use. Defaults to "UTC".
* @returns {string} - A string representing the formatted time according to the specified locale and time zone.
*
* @example
* // Example usage:
* const formattedTime = formatMilliseconds({ time: Date.now(), locale: 'en-US', timeZone: 'America/New_York' });
* console.log(formattedTime); // Output: "02:30 PM" (depending on the current time)
*/
export const formatMilliseconds = ({
time,
locale,
timeZone = "UTC",
}: formatMillisecondsOptions) => {
const timeFormatter = new Intl.DateTimeFormat(locale, {
hour: "2-digit",
minute: "2-digit",
timeZone,
});

return timeFormatter.format(new Date(time));
};

interface IsDayTimeProps {
time: Date;
sunrise: Date;
sunset: Date;
}

/**
* Determines whether a given time is during the day, based on sunrise and sunset times,
* ignoring the date component and only considering the hours and minutes.
*
* @param {Object} params - The parameters object.
* @param {Date} params.time - The current time to check.
* @param {Date} params.sunrise - The time of sunrise.
* @param {Date} params.sunset - The time of sunset.
* @returns {boolean} - Returns `true` if the time is between sunrise and sunset, otherwise `false`.
*/
export const isDayTime = ({
time,
sunrise,
sunset,
}: IsDayTimeProps): boolean => {
const getTimeInMilliseconds = (date: Date) =>
date.getUTCHours() * 60 * 60 +
date.getUTCMinutes() * 60 +
date.getUTCSeconds() * 1000 +
date.getUTCMilliseconds();

const timeInMilliseconds = getTimeInMilliseconds(time);
const sunriseInMilliseconds = getTimeInMilliseconds(sunrise);
const sunsetInMilliseconds = getTimeInMilliseconds(sunset);

return (
timeInMilliseconds >= sunriseInMilliseconds &&
timeInMilliseconds <= sunsetInMilliseconds
);
};

0 comments on commit b08ac01

Please sign in to comment.