Dev.to WebDev πŸ›  Dev πŸ‘ 0 πŸ“– 4 min read

Mapping U.S. area codes to IANA time zones in JavaScript (and the 22 multi-zone edge cases)

Under federal telemarketing rules (47 CFR 64.1200(c)(1) and the FTC's Telemarketing Sales Rule), outbound telephone solicitations to residential lines are restricted to 8:00 a.m. – 9:00 p.m. in the local time of the call

Under federal telemarketing rules (47 CFR 64.1200(c)(1) and the FTC's Telemarketing Sales Rule), outbound telephone solicitations to residential lines are restricted to 8:00 a.m. – 9:00 p.m. in the local time of the called party (and several states enforce stricter windows).

When your system only has a phone number and no verified street address, developers often map the 3-digit area code (NPA) to a UTC offset. Three things trip up naive implementations:

  1. Hardcoded UTC offsets break twice a year when Daylight Saving Time starts (second Sunday in March) and ends (first Sunday in November) under 15 U.S.C. 260a.
  2. Arizona (America/Phoenix) does not observe DST (outside the Navajo Nation), so it matches Mountain Standard Time (UTC-7) in winter and Pacific Daylight Time (UTC-7) in summer.
  3. 22 geographic area codes in the 50 U.S. states span two time zones in NANPA's database (for example, 850 in the Florida Panhandle, 423 in eastern Tennessee, 219 in northwest Indiana, 208 in Idaho, and 308 in Nebraska).

Using Intl.DateTimeFormat with conservative multi-zone bounds

If an area code spans two IANA time zones and you do not know which side of the line the subscriber is on, the only safe rule is to require both zones to be inside the 08:00–21:00 window simultaneously:

const NPA_ZONES = {
  "213": ["America/Los_Angeles"], // Los Angeles, CA
  "415": ["America/Los_Angeles"], // San Francisco, CA
  "408": ["America/Los_Angeles"], // San Jose, CA
  "619": ["America/Los_Angeles"], // San Diego, CA
  "916": ["America/Los_Angeles"], // Sacramento, CA
  "206": ["America/Los_Angeles"], // Seattle, WA
  "503": ["America/Los_Angeles"], // Portland, OR
  "303": ["America/Denver"],      // Denver, CO (Mountain, observes DST)
  "850": ["America/New_York", "America/Chicago"], // FL Panhandle (Eastern + Central)
};

function hourInZone(date, timeZone) {
  const parts = new Intl.DateTimeFormat("en-US", {
    timeZone,
    hour: "numeric",
    minute: "numeric",
    hour12: false,
  }).formatToParts(date);
  const h = Number(parts.find((p) => p.type === "hour").value) % 24;
  const m = Number(parts.find((p) => p.type === "minute").value);
  return h + m / 60;
}

function canCallNow(npa, utcIsoString, { startHour = 8, endHour = 21 } = {}) {
  const zones = NPA_ZONES[npa];
  if (!zones) return { allowed: false, reason: "unknown_npa" };

  const date = new Date(utcIsoString);
  const localHours = zones.map((tz) => ({
    tz,
    hour: +hourInZone(date, tz).toFixed(2),
  }));

  // Every zone covered by the area code must be within [startHour, endHour)
  const allowed = localHours.every(({ hour }) => hour >= startHour && hour < endHour);
  return { npa, allowed, localHours };
}

Testing across UTC timestamps

Let's evaluate canCallNow at two UTC times on July 15 (12:30 UTC and 15:30 UTC):

for (const code of ["213", "303", "850"]) {
  console.log(code, "at 12:30Z ->", canCallNow(code, "2026-07-15T12:30:00Z"));
  console.log(code, "at 15:30Z ->", canCallNow(code, "2026-07-15T15:30:00Z"));
}

Output:

Area Code Region Local time at 12:30 UTC Allowed at 12:30 UTC? Local time at 15:30 UTC Allowed at 15:30 UTC?
213 Los Angeles (America/Los_Angeles) 05:30 (5:30 a.m. PDT) false 08:30 (8:30 a.m. PDT) true
303 Denver (America/Denver) 06:30 (6:30 a.m. MDT) false 09:30 (9:30 a.m. MDT) true
850 Dual-zone (New_York + Chicago) 08:30 EDT / 07:30 CDT false (Central still 7:30 a.m.) 11:30 EDT / 10:30 CDT true

Notice how 850 is blocked at 12:30 UTC: even though the Eastern portion of the area code is at 8:30 a.m., the Central portion is only at 7:30 a.m.. Similarly, in the evening, an 850 call must stop when the Eastern side hits 9:00 p.m. (8:00 p.m. Central), narrowing a two-zone area code's safe window by one hour.

Western & Mountain area codes at a glance

If you are building time-zone lookup tables for major West Coast and Mountain metros, here is how their coverage and overlays break down:

  • Los Angeles (213 area code guide): Assigned in 1947 (America/Los_Angeles); reunited in a boundary elimination overlay with 323 in 2017 and joined by 738.
  • San Francisco & Marin County (415 area code guide): Assigned in 1947 (America/Los_Angeles); overlaid by 628 in 2015.
  • San Jose & Silicon Valley (408 area code guide): Split from 415 in 1959 (America/Los_Angeles); shares Santa Clara County with overlay 669.
  • San Diego (619 area code guide): Split from 714 in 1982 (America/Los_Angeles); re-merged with 858 into a shared overlay in 2018.
  • Sacramento (916 area code guide): Original 1947 Northern California code (America/Los_Angeles); shares Greater Sacramento with overlay 279.
  • Seattle (206 area code guide): Assigned in 1947 (America/Los_Angeles); joined by western Washington overlay 564 in 2025.
  • Portland & Salem (503 area code guide): Assigned in 1947 (America/Los_Angeles); shares northwest Oregon with overlay 971.
  • Denver (303 area code guide): Assigned in 1947 (America/Denver, Mountain Time); shares the Denver metro with overlays 720 and 983.

Remember that mobile number portability means a subscriber with a 213 or 303 number may now live in another time zoneβ€”so whenever your CRM has a confirmed billing or residence state/ZIP for the contact, use the contact's actual location over the phone number's area code.

You can inspect the time zone field (E, C, M, P, and dual-zone codes) for all 372 U.S. area codes in the full NANPA area code table by state or browse city guides in the U.S. area code directory.

Disclosure: I work with the team at EaseDial, which publishes the area code guides and state directory linked above.

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.