Kuinka muuntaa viikkonumero päivämääräväliksi — täydellinen opas

Joku lähettää sinulle aikataulun: ”Toimitus viikolla W23.” Avaat kalenterin ja tuijotat sitä. Mitkä päivät se tarkalleen tarkoittaa?

Viikkonumeroita käytetään kaikkialla projektisuunnittelussa, tuotannossa, vähittäiskaupassa ja logistiikassa — mutta useimmat tuntevat ne vain tunnisteina. Viikkonumeron muuttaminen takaisin kalenteripäiviksi on vähemmän intuitiivista kuin sen pitäisi olla, ja vuodenvaihteeseen liittyvät tapaukset hämäävät jopa kokeneita kehittäjiä.

Tässä oppaassa käydään läpi koko muunnos: viikkonumero → maanantai, viikkonumero → koko aikaväli (maanantai–sunnuntai) sekä käänteinen suunta (päivämäärä → viikkonumero). Mukana koodiesimerkit Pythonille, JavaScriptille, Excelille ja SQL:lle.

Mitä viikkonumero oikeasti kertoo

Ennen kuin lasket mitään, sinun on tiedettävä, mistä viikkonumerointijärjestelmästä numero on peräisin.

ISO 8601 (kansainvälinen standardi): Viikko 1 on se viikko, joka sisältää vuoden ensimmäisen torstain. Viikot ovat maanantaista sunnuntaihin. Vuodessa on 52 tai 53 ISO-viikkoa. Tärkeää: ISO-viikkovuosi voi poiketa kalenterivuodesta. Joulukuun viimeiset päivät ovat joskus seuraavan vuoden viikolla 1.

US-tyyli: Viikko 1 sisältää tammikuun 1. Viikko voi olla sunnuntaista lauantaihin tai maanantaista sunnuntaihin työkalusta riippuen. Tammikuun 1 on aina viikossa 1 — poikkeuksetta.

Tässä oppaassa ”viikkonumero” tarkoittaa ISO 8601 -järjestelmää, ellei toisin mainita. Jos viikkonumero tulee US-tyylisestä työkalusta (kuten Excelin oletus WEEKNUM), kaava on eri — katso oma osio alempaa.

Tarvitset myös vuoden. ”Viikko 23” on merkityksetön ilman vuotta. Käsittele viikkonumeroa aina parina (vuosi, viikko). Vuoden 2025 viikko 23 alkaa 2. kesäkuuta. Vuoden 2026 viikko 23 alkaa 1. kesäkuuta. Vuoden 2026 viikko 1 alkaa 29. joulukuuta vuonna 2025.

Peruskaava: ISO-viikkonumerosta maanantaihin

Jokainen ISO-viikko alkaa maanantaina. ISO-viikon W maanantai vuonna Y löytyy näin:

Maanantai = 4.1. Y + (W - 1) × 7 päivää - viikonpäivä(4.1. Y) + 1

Perustelu: 4. tammikuuta on aina ISO-viikolla 1 (määritelmän mukaan — se on vuoden neljän ensimmäisen päivän joukossa, mikä takaa, että viikko sisältää torstain). Etsi sen viikon maanantai ja siirry eteenpäin (W - 1) viikkoa.

Selkeämpi vastaava muoto:

Viikon 1 maanantai = 4.1. Y - viikonpäivä(4.1. Y) + 1
Viikon W maanantai  = viikon 1 maanantai + (W - 1) × 7

missä viikonpäivä palauttaa 1 maanantaille … 7 sunnuntaille (ISO-viikonpäivän numerointi).

Esimerkki: viikko 23 vuonna 2026

  • 4.1.2026 on sunnuntai. ISO-viikonpäivä = 7.
  • Viikon 1 maanantai: 4.1. − 7 + 1 = 29.12.2025.
  • Viikon 23 maanantai: 29.12.2025 + 22 × 7 = 29.12. + 154 päivää = 1.6.2026.
  • Viikon 23 sunnuntai: 1.6. + 6 = 7.6.2026.

Vuoden 2026 viikko 23 kestää 1.6. (maanantai) – 7.6. (sunnuntai).

Vuodenvaihteen ansa

Yleisin virhe: olettaa, että vuoden Y viikko 1 alkaa aina vuonna Y.

Ei ala.

Viikko 1 on viikko, joka sisältää vuoden ensimmäisen torstain. Jos tuo torstai on tammikuun alussa, viikon 1 maanantai voi olla edellisen vuoden joulukuussa.

Esimerkkejä:

ISO-viikkoVuosiMaanantaiSunnuntai
W1202530. joulukuuta 20245. tammikuuta 2025
W1202629. joulukuuta 20254. tammikuuta 2026
W120274. tammikuuta 202710. tammikuuta 2027
W120283. tammikuuta 20289. tammikuuta 2028

Vuoden 2025 viikko 1 alkaa joulukuussa 2024. Vuoden 2026 viikko 1 alkaa joulukuussa 2025.

Tämä tarkoittaa:

  • 29.–31.12.2025 ovat ISO-viikolla 1 vuoden 2026 puolella, eivät vuoden 2025.
  • Jos joku sanoo ”toimitus viikolla 1 vuonna 2026”, takaraja on viikko, joka alkaa 29.12.2025.

Myös käänteinen ansa on olemassa: joidenkin vuosien viimeiset päivät kuuluvat seuraavan vuoden viikkoon 1, eivät kuluvan vuoden viimeiseen viikkoon. Käytä aina ISO-viikkovuotta (Pythonissa %G, PostgreSQL:ssä isoyear), kun merkitset viikkoja — älä kalenterivuotta.

Koko päivämääräväli mille tahansa viikolle

Kun sinulla on maanantai, loppu on helppoa:

PäiväSiirto maanantaista
Maanantai+0
Tiistai+1
Keskiviikko+2
Torstai+3
Perjantai+4
Lauantai+5
Sunnuntai+6

Viikon W aikaväli on: [maanantai, maanantai + 6 päivää].

Työpäiviä (ma–pe) varten: [maanantai, maanantai + 4 päivää].

Python

from datetime import date, timedelta

def iso_week_to_monday(year: int, week: int) -> date:
    # Jan 4 is always in ISO week 1
    jan4 = date(year, 1, 4)
    # Move back to Monday of that week
    week1_monday = jan4 - timedelta(days=jan4.weekday())
    # Step forward to the target week
    return week1_monday + timedelta(weeks=week - 1)

def iso_week_to_range(year: int, week: int) -> tuple[date, date]:
    monday = iso_week_to_monday(year, week)
    sunday = monday + timedelta(days=6)
    return monday, sunday

# Examples
monday, sunday = iso_week_to_range(2026, 23)
print(monday)   # 2026-06-01
print(sunday)   # 2026-06-07

monday, sunday = iso_week_to_range(2026, 1)
print(monday)   # 2025-12-29  ← note: starts in 2025
print(sunday)   # 2026-01-04

Pythonissa on myös sisäänrakennettu käänteiseen suuntaan (päivämäärä → ISO-viikko):

d = date(2026, 6, 4)
iso_year, iso_week, iso_weekday = d.isocalendar()
print(iso_year, iso_week)  # 2026 23

Käytä d.isocalendar().year (ei d.year), kun tarvitset ISO-vuoden — ne eroavat vuodenvaihteessa.

Käänteiseen hakuun fromisocalendar-metodilla (Python 3.8+):

# Get Monday of ISO week 23, 2026 directly
monday = date.fromisocalendar(2026, 23, 1)  # weekday 1 = Monday
print(monday)  # 2026-06-01

date.fromisocalendar(year, week, weekday) on siistein tapa, jos käytössäsi on Python 3.8 tai uudempi.

JavaScript

JavaScriptissa ei ole natiivia ISO-viikkotukea. Tässä käsin tehty toteutus:

function isoWeekToMonday(year, week) {
  // Jan 4 is always in ISO week 1
  const jan4 = new Date(year, 0, 4)
  const dayOfWeek = jan4.getDay() || 7  // convert Sun=0 to 7
  const week1Monday = new Date(jan4)
  week1Monday.setDate(jan4.getDate() - dayOfWeek + 1)
  
  const monday = new Date(week1Monday)
  monday.setDate(week1Monday.getDate() + (week - 1) * 7)
  return monday
}

function isoWeekToRange(year, week) {
  const monday = isoWeekToMonday(year, week)
  const sunday = new Date(monday)
  sunday.setDate(monday.getDate() + 6)
  return { monday, sunday }
}

// Examples
const { monday, sunday } = isoWeekToRange(2026, 23)
console.log(monday.toISOString().slice(0, 10))  // 2026-06-01
console.log(sunday.toISOString().slice(0, 10))  // 2026-06-07

const w1 = isoWeekToRange(2026, 1)
console.log(w1.monday.toISOString().slice(0, 10))  // 2025-12-29

date-fns-kirjastolla:

import { setISOWeek, setISOWeekYear, startOfISOWeek, endOfISOWeek } from 'date-fns'

function isoWeekToRange(year, week) {
  let d = new Date(year, 0, 4)  // any date in the target year
  d = setISOWeekYear(d, year)
  d = setISOWeek(d, week)
  return {
    monday: startOfISOWeek(d),
    sunday: endOfISOWeek(d)
  }
}

date-fns hoitaa kaikki reunatapaukset oikein ja on suositeltava vaihtoehto tuotantokoodiin.

Excel ja Google Sheets

Excelissä ei ole suoraa ”viikkonumero → päivämäärä” -funktiota, mutta sen voi rakentaa kaavalla.

ISO-viikon W maanantai vuonna Y:

=DATE(Y,1,4) - WEEKDAY(DATE(Y,1,4),2) + 1 + (W-1)*7

Tämä tarkoittaa:

  • DATE(Y,1,4) — 4. tammikuuta
  • WEEKDAY(...,2) — viikonpäivä, jossa maanantai=1 ja sunnuntai=7
  • vähentämällä saat viikon 1 maanantain
  • lisäämällä (W-1)*7 siirryt kohdeviikolle

Koko aikavälille sunnuntai on:

=Monday_formula + 6

Esimerkki (A1 = vuosi, B1 = viikko):

Monday: =DATE(A1,1,4) - WEEKDAY(DATE(A1,1,4),2) + 1 + (B1-1)*7
Sunday: =Monday_cell + 6

Muotoile solut päivämääriksi. Vuodelle 2026, viikolle 1, saat maanantaiksi 29.12.2025 — mikä on oikein.

Käänteinen (päivämäärä → ISO-viikko): käytä ISOWEEKNUM(date). ISO-vuodelle tarvitaan ISOWEEKNUM-artikkelin kiertotapa, koska Excelissä ei ole natiivifunktiota ISO-vuodelle.

SQL

PostgreSQL tukee ISOa kattavimmin:

-- Monday of ISO week W in year Y
SELECT
  make_date(2026, 1, 4)
    + (23 - 1) * 7  -- step to week 23
    - EXTRACT(isodow FROM make_date(2026, 1, 4))::int + 1
    AS week_monday;
-- 2026-06-01

-- Or more cleanly using generate_series for a range lookup
SELECT
  d::date AS week_monday,
  (d + 6)::date AS week_sunday,
  EXTRACT(isoyear FROM d) AS iso_year,
  EXTRACT(week FROM d) AS iso_week
FROM generate_series(
  DATE '2026-01-01',
  DATE '2026-12-31',
  INTERVAL '7 days'
) d
WHERE EXTRACT(week FROM d) = 23
  AND EXTRACT(isoyear FROM d) = 2026;

Selkeä tapa PostgreSQL:ssä käyttää to_date-funktiota ISO-muotoilukoodeilla:

-- Convert ISO year + week to Monday
SELECT to_date('2026' || '23' || '1', 'IYYYIWid') AS monday;
-- 2026-06-01

-- Format: IYYY=ISO year, IW=ISO week, id=ISO day (1=Monday)

Tämä on yksinkertaisin PostgreSQL-tapa: muodosta merkkijono YYYYWWD ja jäsennä se ISO-koodeilla.

MySQL:

-- Monday of ISO week 23, 2026
SELECT STR_TO_DATE('202623 Monday', '%X%V %W');
-- 2026-06-01

-- Or step-based:
SELECT DATE_ADD(
  DATE_ADD(STR_TO_DATE('2026-01-04', '%Y-%m-%d'),
    INTERVAL (-(WEEKDAY(STR_TO_DATE('2026-01-04', '%Y-%m-%d')))) DAY),
  INTERVAL (23 - 1) * 7 DAY
) AS week_monday;

SQL Server:

-- Monday of ISO week 23, 2026
DECLARE @year INT = 2026, @week INT = 23

SELECT DATEADD(
  DAY,
  (@week - 1) * 7
    - (DATEPART(WEEKDAY, DATEFROMPARTS(@year, 1, 4)) + 5) % 7,
  DATEFROMPARTS(@year, 1, 4)
) AS week_monday;
-- 2026-06-01

US-tyylinen viikkonumero → päivämäärät

Jos viikkonumero tulee US-tyylisestä järjestelmästä (viikko 1 = sisältää 1.1., viikot alkavat sunnuntaina tai maanantaina), kaava on yksinkertaisempi, koska vuodenvaihdeongelmaa ei ole:

Viikon alku (sunnuntai-pohjainen):

Week_start = DATE(Y, 1, 1) + (W - 1) × 7 - WEEKDAY(DATE(Y, 1, 1), 1)

missä WEEKDAY palauttaa 1 sunnuntaille … 7 lauantaille.

Mutta US-tyyliset viikkonumerot ovat aikatauluissa ja logistiikassa paljon harvinaisempia kuin ISO. Jos joku antaa viikkonumeron määrittelemättä järjestelmää, oleta ISO — erityisesti kansainvälisissä tai eurooppalaisissa yhteyksissä.

Vuosi 2026: pikaopas ISO-viikoille 1–10 ja 48–53

ISO-viikkoVuosiMaanantaiSunnuntai
W1202629.12.20254.1.2026
W220265.1.202611.1.2026
W3202612.1.202618.1.2026
W4202619.1.202625.1.2026
W5202626.1.20261.2.2026
W620262.2.20268.2.2026
W720269.2.202615.2.2026
W8202616.2.202622.2.2026
W9202623.2.20261.3.2026
W1020262.3.20268.3.2026
...
W48202623.11.202629.11.2026
W49202630.11.20266.12.2026
W5020267.12.202613.12.2026
W51202614.12.202620.12.2026
W52202621.12.202627.12.2026
W53202628.12.20263.1.2027

Huomaa: vuoden 2026 viikko 1 alkaa 29.12.2025. Huomaa myös: vuoden 2026 viikko 53 päättyy 3.1.2027 — 2026 on 53-viikkoinen vuosi.

Yleisimmät virheet tiivistettynä

Vuoden puuttuminen. ”Viikko 8” on epäselvä. Käytä aina muotoa 2026-W08 tai vastaavaa.

Kalenterivuoden käyttäminen ISO-viikkovuoden sijaan. 29.12.2025 on ISO-viikolla 1 vuonna 2026, ei 2025. Jos tallennat sen vuodelle 2025, se päätyy väärään “lokeroon”.

Olettaa, että viikko 1 alkaa 1.1. Monina vuosina se alkaa 29., 30. tai 31.12. Jos haluat, että 1.1. on aina viikossa 1, käytät US-järjestelmää, et ISOa.

Off-by-one maanantaikaavassa. 4. tammikuuta -ankkuri on olennainen — ei 1. tammikuuta (joka voi kuulua edellisen vuoden viimeiseen viikkoon). Jos käytät 1. tammikuuta ankkurina, saat vääriä tuloksia vuosina, joissa 1. tammikuuta osuu viikon loppupuolelle.

Vuodenvaihteen testaamatta jättäminen. Kaikki päivämäärälogiikka tulisi testata päivillä 28.–31.12. ja 1.–4.1. Näinä 4–7 päivänä sijaitsevat kaikki reunatapaukset.

Käytä ISO Week Number Calculator -työkalua hakeaksesi minkä tahansa viikkonumeron päivämäärävälin, tai tarkista current week number ja tämän päivän ISO-viikkopäivämääräväli.