Skip to content

Commit f611a86

Browse files
committed
Move repeated time validation checks to utils.
1 parent d3bb3d5 commit f611a86

File tree

3 files changed

+80
-38
lines changed

3 files changed

+80
-38
lines changed

src/pages/ContextFeed.jsx

Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ import {
2727
isoToUTC,
2828
getDayobsStartUTC,
2929
getDayobsEndUTC,
30-
millisToDateTime,
3130
utcDateTimeStrToMillis,
31+
getValidTimeRange,
3232
} from "@/utils/timeUtils";
3333
import { getDatetimeFromDayobsStr } from "@/utils/utils";
3434

@@ -80,21 +80,7 @@ function ContextFeed() {
8080
const [selectedTimeRange, setSelectedTimeRange] = useState(() => {
8181
const startMillis = Number(startTime);
8282
const endMillis = Number(endTime);
83-
84-
const [fullStart, fullEnd] = fullTimeRange;
85-
86-
const isValid =
87-
startMillis &&
88-
endMillis &&
89-
!Number.isNaN(startMillis) &&
90-
!Number.isNaN(endMillis) &&
91-
startMillis >= fullStart.toMillis() &&
92-
endMillis <= fullEnd.toMillis();
93-
94-
if (isValid) {
95-
return [millisToDateTime(startMillis), millisToDateTime(endMillis)];
96-
}
97-
return fullTimeRange;
83+
return getValidTimeRange(startMillis, endMillis, fullTimeRange);
9884
});
9985

10086
const [contextFeedData, setContextFeedData] = useState([]);
@@ -139,30 +125,11 @@ function ContextFeed() {
139125
useEffect(() => {
140126
const startMillis = Number(startTime);
141127
const endMillis = Number(endTime);
128+
const newRange = getValidTimeRange(startMillis, endMillis, fullTimeRange);
142129

143-
// Url params are optional; make sure we don't set NaNs
144-
const hasValidTimes =
145-
startMillis != null &&
146-
!Number.isNaN(startMillis) &&
147-
endMillis != null &&
148-
!Number.isNaN(endMillis);
149-
150-
// Only accept times if they fall inside the dayobs range
151-
const hasTimesInRange =
152-
startMillis >= fullTimeRange[0].toMillis() &&
153-
endMillis <= fullTimeRange[1].toMillis();
154-
155-
const newRange =
156-
hasValidTimes && hasTimesInRange
157-
? [millisToDateTime(startMillis), millisToDateTime(endMillis)]
158-
: fullTimeRange;
159-
160-
// Only update state if the numeric values changed
161-
const oldRange = selectedTimeRange;
162130
if (
163-
!oldRange ||
164-
oldRange[0].toMillis() !== newRange[0].toMillis() ||
165-
oldRange[1].toMillis() !== newRange[1].toMillis()
131+
newRange[0].toMillis() !== selectedTimeRange[0].toMillis() ||
132+
newRange[1].toMillis() !== selectedTimeRange[1].toMillis()
166133
) {
167134
setSelectedTimeRange(newRange);
168135
}

src/utils/timeUtils.jsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,33 @@ const dayobsAtMidnight = (dt, format = "yyyy-LL-dd") => {
160160
return dt.minus({ minutes: 1 }).toFormat(format);
161161
};
162162

163+
/**
164+
* Validate start/end millis and convert to Luxon DateTime objects if valid.
165+
* Otherwise return the provided fullTimeRange.
166+
*
167+
* @param {number} startMillis
168+
* @param {number} endMillis
169+
* @param {[DateTime, DateTime]} fullTimeRange
170+
* @returns {[DateTime, DateTime]} start/end DateTimes
171+
*/
172+
function getValidTimeRange(startMillis, endMillis, fullTimeRange) {
173+
if (
174+
startMillis != null &&
175+
endMillis != null &&
176+
!Number.isNaN(startMillis) &&
177+
!Number.isNaN(endMillis)
178+
) {
179+
const [fullStart, fullEnd] = fullTimeRange;
180+
if (
181+
startMillis >= fullStart.toMillis() &&
182+
endMillis <= fullEnd.toMillis()
183+
) {
184+
return [millisToDateTime(startMillis), millisToDateTime(endMillis)];
185+
}
186+
}
187+
return fullTimeRange;
188+
}
189+
163190
export {
164191
isoToTAI,
165192
isoToUTC,
@@ -173,6 +200,7 @@ export {
173200
utcDateTimeStrToTAIMillis,
174201
utcDateTimeStrToMillis,
175202
dayobsAtMidnight,
203+
getValidTimeRange,
176204
ISO_DATETIME_FORMAT,
177205
TAI_OFFSET_SECONDS,
178206
};

tests/timeUtils.test.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
utcDateTimeStrToTAIMillis,
1515
utcDateTimeStrToMillis,
1616
dayobsAtMidnight,
17+
getValidTimeRange,
1718
} from "../src/utils/timeUtils";
1819

1920
const TAI_OFFSET_SECONDS = 37;
@@ -114,4 +115,50 @@ describe("timeUtils", () => {
114115
expect(dayobsAtMidnight(dt, "yyyyLLdd")).toBe("20250817");
115116
});
116117
});
118+
119+
describe("getValidTimeRange", () => {
120+
const fullTimeRange = [
121+
getDayobsStartUTC("20250818"),
122+
getDayobsEndUTC("20250818"),
123+
];
124+
125+
it("returns start/end DateTimes if millis are valid and in range", () => {
126+
const startMillis =
127+
getDayobsStartUTC("20250818").toMillis() + 6 * 3600 * 1000; // +6h
128+
const endMillis =
129+
getDayobsStartUTC("20250818").toMillis() + 18 * 3600 * 1000; // +18h
130+
131+
const result = getValidTimeRange(startMillis, endMillis, fullTimeRange);
132+
133+
expect(result[0].toMillis()).toBe(startMillis);
134+
expect(result[1].toMillis()).toBe(endMillis);
135+
});
136+
137+
it("returns fullTimeRange if startMillis is null", () => {
138+
const endMillis = fullTimeRange[1].toMillis();
139+
const result = getValidTimeRange(null, endMillis, fullTimeRange);
140+
expect(result).toEqual(fullTimeRange);
141+
});
142+
143+
it("returns fullTimeRange if endMillis is NaN", () => {
144+
const startMillis = fullTimeRange[0].toMillis();
145+
const result = getValidTimeRange(startMillis, NaN, fullTimeRange);
146+
expect(result).toEqual(fullTimeRange);
147+
});
148+
149+
it("returns fullTimeRange if times are out of range", () => {
150+
const startMillis = fullTimeRange[0].toMillis() - 3600 * 1000; // before range
151+
const endMillis = fullTimeRange[1].toMillis() + 3600 * 1000; // after range
152+
153+
const result = getValidTimeRange(startMillis, endMillis, fullTimeRange);
154+
expect(result).toEqual(fullTimeRange);
155+
});
156+
157+
it("returns fullTimeRange if times partially out of range", () => {
158+
const startMillis = fullTimeRange[0].toMillis() + 2 * 3600 * 1000; // in range
159+
const endMillis = fullTimeRange[1].toMillis() + 3600 * 1000; // out of range
160+
const result = getValidTimeRange(startMillis, endMillis, fullTimeRange);
161+
expect(result).toEqual(fullTimeRange);
162+
});
163+
});
117164
});

0 commit comments

Comments
 (0)