Files
jinhojang6 1acdba0f5f refactor(blog): rename all Press identifiers/files to Blog, ROUTES.blog
Follow-up to the LPE→Blog rename: purge "Press" from code symbol and file
names and make every consumer use ROUTES.blog instead of a hardcoded path.

- ROUTES: key press -> blog (value /blog); all consumers use ROUTES.blog
- Rename files: lib/press-engine.ts -> lib/blog-engine.ts (+ test),
  blog/_sections/press-atoms.tsx -> blog-atoms.tsx,
  home/press-section.tsx -> blog-section.tsx,
  public/images/press-engine/ -> public/images/blog-engine/
- Rename code symbols: PressArticleRow/PressPodcastRow/PressHero/PressCopy/
  PressRowLink/PressSection/PressCard(Props)/PressPage, getLatest*Press*,
  getPressPageData, getPress*Image*, PRESS_ORIGIN/PRESS_HERO_IMAGE, pressT, etc.
- Rename code-referenced data keys: i18n namespace pages.press -> pages.blog
  (removed stale orphan pages.blog stub), section key home.press -> home.blog,
  DOM id press -> blog
- packages/ui: NavOverlayPressItem -> NavOverlayBlogItem, press/pressSeeAllHref
  -> blog/blogSeeAllHref (rebuilt dist); navigation.json + site schema press -> blog

Intentionally kept (not LPE branding): circles "press" date-format surface
(formatPressDate/event date style), image asset filenames (press-*.webp,
press-hero.jpg), and link-policy legacy-fixture guards.

Verified: web tsc clean, 61 web tests pass, content types + 29 validations pass,
@acid-info/logos-ui rebuilds clean.
2026-06-03 02:04:35 +09:00

69 lines
2.2 KiB
TypeScript

/**
* Centralised date formatters.
*
* Every page/section that renders a published-at or event date should call
* one of these instead of redefining `Intl.DateTimeFormat` inline. Keeping
* format choices in one place means a copy change ("MM.DD.YY" → "DD/MM/YY")
* is a one-line edit.
*
* All formatters operate in UTC and the `en-US` locale to match the Figma
* specs; localisation hooks belong in their own helper if/when needed.
*/
const UTC_LOCALE = 'en-US'
const UTC = 'UTC'
/**
* `MM.DD.YY` (UTC, `en-US` 2-digit). Used by blog articles and
* tech-domain related-articles cards.
*/
export function formatDateMdy2(iso: string): string {
const parts = new Intl.DateTimeFormat(UTC_LOCALE, {
timeZone: UTC,
year: '2-digit',
month: '2-digit',
day: '2-digit',
}).formatToParts(new Date(iso))
const month = parts.find((p) => p.type === 'month')?.value ?? ''
const day = parts.find((p) => p.type === 'day')?.value ?? ''
const year = parts.find((p) => p.type === 'year')?.value ?? ''
return `${month}.${day}.${year}`
}
/**
* `Jan 15, 2025` (UTC, `en-US` short month + numeric year). Used by
* builders-hub detail pages. Returns the input string unchanged when the
* argument cannot be parsed as a date.
*/
export function formatDateLong(iso: string): string {
const d = new Date(iso)
if (Number.isNaN(d.getTime())) return iso
return d.toLocaleDateString(UTC_LOCALE, {
timeZone: UTC,
year: 'numeric',
month: 'short',
day: 'numeric',
})
}
/**
* Short timezone offset label (`PST`, `KST`, ...). Used by event lists
* that show local-time-aware metadata.
*
* Falls back to the input `timeZone` string when the runtime rejects it
* (e.g. malformed zone, ICU data missing) — callers want to keep rendering
* something rather than blow up the whole event list.
*/
export function formatTzOffsetLabel(timeZone: string, iso: string): string {
let parts: Intl.DateTimeFormatPart[]
try {
parts = new Intl.DateTimeFormat(UTC_LOCALE, {
timeZone,
timeZoneName: 'shortOffset',
}).formatToParts(new Date(iso))
} catch {
return timeZone
}
return parts.find((part) => part.type === 'timeZoneName')?.value ?? timeZone
}