Skip to content

Commit ee71f8d

Browse files
committed
Gracefully handle non-ASCII characters in timezone
1 parent f833807 commit ee71f8d

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

services/user-feeds-next/src/articles/parser/article-parser.test.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ describe("article-parser", () => {
504504
assert.strictEqual(flattenedArticle[`b${DL}c${DL}d${DL}e`], dayjs(article.b.c.d.e).tz(dateTimezone).format());
505505
});
506506

507-
it("falls back to UTC for invalid timezones", () => {
507+
it("falls back to UTC for invalid timezones (non-ASCII)", () => {
508508
const date = new Date("2024-01-15T12:00:00Z");
509509
const article = {
510510
id: "hello world",
@@ -526,5 +526,25 @@ describe("article-parser", () => {
526526
// Should fall back to UTC instead of throwing
527527
assert.strictEqual(flattenedArticle.a, dayjs(date).utc().locale("en").format());
528528
});
529+
530+
it("falls back to UTC for invalid timezones (invalid IANA name)", () => {
531+
const date = new Date("2024-01-15T12:00:00Z");
532+
const article = {
533+
id: "hello world",
534+
a: date,
535+
};
536+
537+
const flattenedArticle = flattenArticle(article, {
538+
formatOptions: {
539+
dateFormat: undefined,
540+
dateTimezone: "Invalid/Timezone",
541+
dateLocale: undefined,
542+
},
543+
useParserRules: [],
544+
});
545+
546+
// Should fall back to UTC instead of throwing
547+
assert.strictEqual(flattenedArticle.a, dayjs(date).utc().locale("en").format());
548+
});
529549
});
530550
});

services/user-feeds-next/src/articles/parser/article-parser.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,18 @@ export function flattenArticle(
8383
}
8484

8585
if (value instanceof Date) {
86-
const useTimezone = options.formatOptions?.dateTimezone || "UTC";
86+
const requestedTimezone = options.formatOptions?.dateTimezone || "UTC";
8787
let dateVal;
8888

8989
try {
90-
dateVal = dayjs(value).tz(useTimezone);
90+
// eslint-disable-next-line no-control-regex
91+
if (/[^\x00-\x7F]/.test(requestedTimezone)) {
92+
// Non-ASCII characters (e.g., Unicode minus) aren't valid in timezones
93+
throw new Error("Invalid timezone");
94+
}
95+
dateVal = dayjs(value).tz(requestedTimezone);
9196
} catch {
92-
// Invalid timezone (e.g., Unicode minus character instead of ASCII hyphen)
93-
// Fall back to UTC
94-
logger.debug(`Invalid timezone "${useTimezone}", falling back to UTC`);
97+
logger.debug(`Invalid timezone "${requestedTimezone}", falling back to UTC`);
9598
dateVal = dayjs(value).utc();
9699
}
97100

services/user-feeds-next/src/http/handlers/preview.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
CustomPlaceholderStepType,
1919
type CustomPlaceholder,
2020
} from "../../articles/formatter";
21-
import type { Article } from "../../articles/parser";
2221
import {
2322
CustomPlaceholderRegexEvalException,
2423
FiltersRegexEvalException,

0 commit comments

Comments
 (0)