-
-
Notifications
You must be signed in to change notification settings - Fork 34
Description
We want to take a timezone like "Europe/Oslo" and figure out what its offset is compared to UTC. During winter, Oslo is +01:00 (one hour ahead), and during summer it's +02:00 (daylight saving time).
Using formatToParts()
Here's the clever part. JavaScript has this thing called Intl.DateTimeFormat that can give you the current time in ANY timezone. But here's what makes it special: there's a method called formatToParts() that breaks down a date into pieces.
const format = new Intl.DateTimeFormat('en-US', {
timeZone: 'Europe/Oslo',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
});
const parts = format.formatToParts();This gives you an array like:
[
{ type: 'month', value: '11' },
{ type: 'literal', value: '/' },
{ type: 'day', value: '24' },
{ type: 'year', value: '2025' },
// ... and so on
]Pretty neat, right? Each part of the date is labeled with its type. We can now extract just the pieces we need and ignore those literal separators.
Why m - 1?
Here's something that trips people up: when you use Date.UTC(), the month parameter is zero-based. That means:
- January = 0
- February = 1
- March = 2
- ... and so on
But formatToParts() gives us the month as a normal human would see it (1 for January, 2 for February, etc.). So we need to subtract 1 to convert it:
const m = Number(parts.month); // This is 11 for November
const asUTC = Date.UTC(y, m - 1, d, hh, mm, ss); // We pass 10 for NovemberWhat's Date.UTC() Doing?
Date.UTC() takes date components and returns the number of milliseconds since January 1, 1970 (the Unix epoch) in UTC time.
So here's the clever calculation:
- We ask "what time is it right now in Oslo?" →
formatToParts()tells us - We convert those Oslo time components to a UTC timestamp →
Date.UTC() - We compare that to the actual current UTC time →
Date.now() - The difference is the offset!
const asUTC = Date.UTC(y, m - 1, d, hh, mm, ss);
const offset = Math.round((asUTC - Date.now()) / 60000);We divide by 60,000 because we want the offset in minutes (1 minute = 60,000 milliseconds).
Formatting the Final Result
Once we have the offset in minutes, we just need to format it nicely:
function formatOffset(minutes) {
const sign = minutes >= 0 ? '+' : '-';
const abs = Math.abs(minutes);
const hrs = String(Math.floor(abs / 60)).padStart(2, '0');
const mins = String(abs % 60).padStart(2, '0');
return `${sign}${hrs}:${mins}`;
}So if Oslo is 60 minutes ahead of UTC, we get +01:00. If New York is 300 minutes behind, we get -05:00.
And that's it! A simple but effective way to get timezone offsets without any external libraries.