Miksi Excel, SQL, Python ja JavaScript antavat eri viikkonumeron samalle päivälle
Lasket viikkonumeron Pythonissa, avaat saman päivän Excelissä, ja numerot eivät täsmää. Ajet SQL-kyselyn ja saat kolmannen tuloksen. Haet netistä ja löydät neljännen.
Tämä ei ole bugi. Se on suunnitteluvalinta, jonka jokainen työkalu tekee eri tavalla — ja useimmat eivät dokumentoi sitä tarpeeksi näkyvästi.
Käytössä on vähintään kaksi suurta viikkonumerointijärjestelmää, useita variaatioita kummankin sisällä, eikä ole mitään universaalia oletusta. Kun ymmärrät erot, ristiriitojen selvittäminen vie sekunteja. Ennen sitä ne ovat raivostuttavia.
Kaksi pääjärjestelmää
ISO 8601 (käytössä suurimmassa osassa Eurooppaa, kansainvälisessä liiketoiminnassa ja tieteellisissä yhteyksissä)
- Viikot alkavat maanantaina ja päättyvät sunnuntaina
- Viikko 1 on viikko, joka sisältää vuoden ensimmäisen torstain
- Vuodessa on 52 tai 53 viikkoa
- Viikkovuosi voi poiketa kalenterivuodesta rajapäivinä
USA-/”yksinkertainen” järjestelmä (käytössä Pohjois-Amerikassa ja monien taulukkotyökalujen oletuksena)
- Viikot alkavat sunnuntaina ja päättyvät lauantaina (tai joskus maanantaista sunnuntaihin, riippuen lokalisaatiosta)
- Viikko 1 on viikko, joka sisältää tammikuun 1. päivän
- Tammikuun 1. päivä on aina viikolla 1 riippumatta viikonpäivästä
- Vuoden lopun osittaiset viikot saavat korkeat numerot (52 tai 53), eikä niitä siirretä seuraavan vuoden viikoksi 1
Käytännön ero näkyy selvimmin joulukuun lopussa ja tammikuun alussa.
| Päivä | ISO-viikko | US-viikko (sunnuntai alku) |
|---|---|---|
| December 28, 2025 | Week 52, 2025 | Week 53, 2025 |
| December 29, 2025 | Week 1, 2026 | Week 53, 2025 |
| December 30, 2025 | Week 1, 2026 | Week 53, 2025 |
| December 31, 2025 | Week 1, 2026 | Week 53, 2025 |
| January 1, 2026 | Week 1, 2026 | Week 1, 2026 |
| January 2, 2026 | Week 1, 2026 | Week 1, 2026 |
| January 3, 2026 | Week 1, 2026 | Week 1, 2026 |
| January 4, 2026 | Week 1, 2026 | Week 2, 2026 |
29.–31.12.2025 ovat ISO-järjestelmässä viikolla 1 vuonna 2026 — koska kyseisen viikon torstai (1.1.) on vuonna 2026. US-järjestelmä pitää ne viikkona 53 vuonna 2025.
Excel: WEEKNUM vs ISOWEEKNUM
Excelissä on kaksi erillistä funktiota, mikä on selkeämpää kuin useimmissa työkaluissa.
WEEKNUM(date, [return_type]) — US-tyylinen, viikonalun voi määrittää
return_type-argumentti määrittää, mikä viikonpäivä aloittaa viikon:
| return_type | Viikko alkaa |
|---|---|
| 1 (oletus) | sunnuntai |
| 2 | maanantai |
| 11 | maanantai |
| 12 | tiistai |
| 13 | keskiviikko |
| 14 | torstai |
| 15 | perjantai |
| 16 | lauantai |
| 17 | sunnuntai |
| 21 | maanantai (ISO 8601) |
return_type = 21 saa WEEKNUM-funktion käyttäytymään ISO-tyylisesti — mutta tämä on heikosti dokumentoitu ja monilta käyttäjiltä jää huomaamatta.
ISOWEEKNUM(date) — ISO 8601, aina maanantai alku, torstaisääntö
Tämä lisättiin Excel 2013:ssa. Se palauttaa oikean ISO-viikkonumeron ja on yksiselitteinen.
=ISOWEEKNUM("2025-12-31") → 1 (viikko 1 vuonna 2026)
=WEEKNUM("2025-12-31", 1) → 53 (viikko 53 vuonna 2025, sunnuntai alku)
=WEEKNUM("2025-12-31", 2) → 53 (viikko 53 vuonna 2025, maanantai alku)
=WEEKNUM("2025-12-31", 21) → 1 (ISO-yhteensopiva, sama kuin ISOWEEKNUM)
Yleinen virhe: WEEKNUM-funktion käyttäminen oletusasetuksilla, kun vertaillaan ISO-järjestelmään. Numerot täsmäävät suurimman osan vuodesta, mutta eroavat hiljaa vuoden vaihteessa.
Google Sheets: samat funktiot, samat sudenkuopat
Google Sheetsissä on sekä WEEKNUM että ISOWEEKNUM, ja niiden käyttäytyminen on sama kuin Excelissä. Oletus-WEEKNUM on US-tyylinen, viikko alkaa sunnuntaina. ISOWEEKNUM on ISO 8601.
Yksi ero: Google Sheets on johdonmukaisempi ISO-viikkovuoden kanssa, kun käytät ISOWEEKNUM-funktion rinnalla YEAR-funktiota. Jos kirjoitat =YEAR("2025-12-31"), saat 2025, mutta ISO-viikko kuuluu vuoteen 2026. Ei ole yhtä sisäänrakennettua funktiota, joka palauttaisi ISO-viikkovuoden — se pitää laskea:
=IF(ISOWEEKNUM(A1) > 50, IF(MONTH(A1) = 1, YEAR(A1) - 1, YEAR(A1)),
IF(ISOWEEKNUM(A1) < 3, IF(MONTH(A1) = 12, YEAR(A1) + 1, YEAR(A1)),
YEAR(A1)))
Tämä on pitkä. Jos teet Sheetsissä paljon viikkovuosi-logiikkaa, on usein siistimpää viedä data Pythoniin tai SQL:ään.
Python: isocalendar() on ISO, mutta strftime('%W') ei ole
Pythonin datetime-moduuli tarjoaa kaksi eri lähestymistapaa.
date.isocalendar() — ISO 8601, palauttaa (year, week, weekday)
from datetime import date
d = date(2025, 12, 31)
d.isocalendar()
# IsoCalendarDate(year=2026, week=1, weekday=3)
Huomaa, että palautettu vuosi on ISO-viikkovuosi (2026), ei kalenterivuosi (2025). Tämä on oikein ja tärkeää — jos tarvitset viikon “vuoden” raportointiin, käytä iso_year-arvoa, ei d.year-arvoa.
strftime('%W') ja strftime('%U') — US-tyylinen, eri viikonalut
d.strftime('%W') # Viikkonumero, maanantai viikon ensimmäinen päivä → '52'
d.strftime('%U') # Viikkonumero, sunnuntai viikon ensimmäinen päivä → '52'
d.strftime('%V') # ISO-viikkonumero → '01'
d.strftime('%G') # ISO-viikkovuosi → '2026'
Yhdistelmä %V / %G on ISO-oikea. %W / %U ovat US-tyylisiä ja eroavat ISO:sta vuoden vaihteessa.
Yleinen virhe: d.strftime('%W')-funktion käyttäminen viikkonumeroon, kun muut järjestelmät käyttävät ISO:ta. Se toimii 48+ viikkoa vuodesta ja alkaa sitten hiljaa poiketa joulukuussa ja tammikuussa.
# Väärin ISO-vertailuun — vuoden raja antaa ristiriidan
week = int(d.strftime('%W'))
# Oikein ISO:lle
iso_year, iso_week, _ = d.isocalendar()
JavaScript: ei sisäänrakennettua — laske itse
JavaScriptin Date-oliolla ei ole sisäänrakennettua viikkonumerometodia. Date.getDay() palauttaa 0 (sunnuntai) – 6 (lauantai). Viikkonumero pitää laskea itse tai käyttää kirjastoa kuten date-fns tai dayjs.
ISO-viikon manuaalinen laskenta:
function isoWeek(date) {
const d = new Date(date)
d.setHours(0, 0, 0, 0)
// Thursday in current week decides the year
d.setDate(d.getDate() + 3 - (d.getDay() + 6) % 7)
const jan4 = new Date(d.getFullYear(), 0, 4)
return 1 + Math.round(((d - jan4) / 86400000 - 3 + (jan4.getDay() + 6) % 7) / 7)
}
function isoWeekYear(date) {
const d = new Date(date)
d.setDate(d.getDate() + 3 - (d.getDay() + 6) % 7)
return d.getFullYear()
}
isoWeek(new Date('2025-12-31')) // 1
isoWeekYear(new Date('2025-12-31')) // 2026
date-fns:n käyttö:
import { getISOWeek, getISOWeekYear } from 'date-fns'
getISOWeek(new Date('2025-12-31')) // 1
getISOWeekYear(new Date('2025-12-31')) // 2026
Yleinen virhe: Kirjoittaa yksinkertainen Math.ceil(dayOfYear / 7) ja kutsua sitä viikkonumeroksi. Se ei vastaa ISO- eikä US-standardia — se on täysin eri (ja väärä) järjestelmä.
SQL: riippuu tietokannasta
Jokainen iso tietokanta käsittelee viikkonumerot hieman eri tavalla.
PostgreSQL — ISO oletuksena
SELECT EXTRACT(week FROM DATE '2025-12-31');
-- Returns 1 (ISO week)
SELECT DATE_PART('week', DATE '2025-12-31');
-- Returns 1 (same, ISO)
-- Get ISO week year
SELECT EXTRACT(isoyear FROM DATE '2025-12-31');
-- Returns 2026
PostgreSQL:n EXTRACT(week ...) noudattaa ISO 8601:ä. Viikkovuoden saa isoyear-kentästä.
MySQL / MariaDB — useita tiloja
-- Mode 3 is ISO 8601 (Monday start, week 1 has Thursday)
SELECT WEEK('2025-12-31', 3); -- 1
-- Mode 0 (default) is US-style, Sunday start
SELECT WEEK('2025-12-31', 0); -- 53
SELECT WEEK('2025-12-31'); -- 53 (default mode 0)
-- YEARWEEK returns combined year+week
SELECT YEARWEEK('2025-12-31', 3); -- 202601
MySQL:n mode-argumentti on kriittinen ja siinä on 8 vaihtoehtoa (0–7). Mode 3 on ISO. Oletus (mode 0) on US-tyylinen. Tämä on yleinen bugien lähde, kun vaihdetaan tietokantamoottoria.
SQL Server — ei ISO oletuksena
-- Default DATEPART(week, ...) is not ISO
SELECT DATEPART(week, '2025-12-31'); -- 53
-- ISO week: use isowk or iso_week
SELECT DATEPART(isowk, '2025-12-31'); -- 1
SELECT DATEPART(iso_week, '2025-12-31'); -- 1 (same)
SQL Serverin oletus DATEPART(week, ...) on US-tyylinen. isowk on ISO-versio. Jos teet raportteja, joita verrataan eurooppalaisiin järjestelmiin, käytä aina isowk.
SQLite — ei natiivia viikkofunktiota
SQLite:ssa ei ole WEEKNUM- tai EXTRACT(week ...)-funktiota. Käytetään strftime:a:
-- '%W' is Monday-start, US-style
SELECT strftime('%W', '2025-12-31'); -- 52
-- ISO week requires a workaround
SELECT (strftime('%j', date('2025-12-31', '-3 days', 'weekday 4')) - 1) / 7 + 1;
-- 1
ISO-kiertotie etsii viikon torstain ja laskee sen perusteella. Se on oikein, mutta ei ilmeinen.
Pika-taulukko
| Työkalu | ISO-viikko | US-viikko | Huomiot |
|---|---|---|---|
| Excel | ISOWEEKNUM() tai WEEKNUM(d, 21) | WEEKNUM() oletus | ISOWEEKNUM lisättiin 2013 |
| Google Sheets | ISOWEEKNUM() | WEEKNUM() oletus | Sama kuin Excel |
| Python | date.isocalendar()[1] tai %V | %W (ma) / %U (su) | Käytä %G ISO-viikkovuodelle |
| JavaScript | Manuaalisesti tai date-fns getISOWeek() | Manuaalisesti | Ei natiivia viikkonumeroa |
| PostgreSQL | EXTRACT(week ...) | Ei sisäänrakennettua | ISO oletuksena |
| MySQL | WEEK(d, 3) | WEEK(d) tai WEEK(d, 0) | Mode 3 = ISO |
| SQL Server | DATEPART(isowk, d) | DATEPART(week, d) | Oletus on US |
| SQLite | Kiertotie vaaditaan | strftime('%W', d) | Ei natiivia tukea |
Näin vältät ristiriidat käytännössä
Valitse yksi järjestelmä ja pakota se kaikkialle. ISO on yleensä parempi oletus uusille järjestelmille — se on kansainvälisesti standardoitu ja se, mitä useimmat modernit kirjastot toteuttavat.
Tallenna aina ISO-viikkovuosi viikkonumeron rinnalle. Viikko 1 vuonna 2026 ja viikko 1 vuonna 2025 ovat eri viikkoja. Sarake, jossa on pelkkä 1, on epäselvä ilman vuotta.
Tarkista vuoden vaihteen tapaukset erikseen. Päivät 28.–31.12. ja 1.–3.1. ovat ne, joissa erot syntyvät. Testaa putkesi päivillä tältä väliltä ennen käyttöönottoa.
Jos epäröit, tallenna ja vertaa kokonaisia päivämääriä. Viikkonumerot ovat näyttöä ja raportointia varten, eivät ensisijaisia avaimia tai liitoksia varten. Jos liität dataa järjestelmien välillä viikkonumerolla, muunna ensin kanoniseen päivään (viikon maanantai).
Käytä ISO-viikkonumerolaskuria tarkistaaksesi oikean ISO-viikkonumeron mille tahansa päivälle, mukaan lukien koko vuoden kalenterinäkymä.