چگونه یک شماره هفته را به بازه تاریخ تبدیل کنیم — راهنمای کامل

کسی برنامه‌ای برایتان می‌فرستد. «تحویل در W23.» تقویم را باز می‌کنید و به آن خیره می‌شوید. این دقیقاً چه تاریخی است؟

شماره‌های هفته در برنامه‌ریزی پروژه، تولید، خرده‌فروشی و لجستیک به طور گسترده استفاده می‌شوند — اما بیشتر افراد آن‌ها را فقط به عنوان برچسب می‌شناسند. تبدیل شماره هفته به تاریخ‌های واقعی تقویم کمتر از آنچه باید باشد شهودی است، و موارد مرز سال حتی توسعه‌دهندگان با تجربه را هم گیج می‌کند.

این راهنما تبدیل کامل را پوشش می‌دهد: شماره هفته به دوشنبه، شماره هفته به بازه کامل تاریخ (دوشنبه تا یکشنبه)، و معکوس (تاریخ به شماره هفته). با کد برای پایتون، جاوااسکریپت، اکسل و SQL.

شماره هفته واقعاً چه چیزی را نشان می‌دهد

قبل از هر محاسبه‌ای، باید بدانید شماره از کدام سیستم شماره‌گذاری هفته آمده است.

ISO 8601 (استاندارد بین‌المللی): هفته ۱ هفته‌ای است که اولین پنجشنبه سال را در بر می‌گیرد. هفته‌ها از دوشنبه تا یکشنبه هستند. یک سال ۵۲ یا ۵۳ هفته ISO دارد. نکته مهم — سال هفته ISO می‌تواند با سال تقویمی متفاوت باشد. آخرین روزهای دسامبر گاهی در هفته ۱ سال بعد قرار دارند.

سبک آمریکایی: هفته ۱ شامل ۱ ژانویه است. هفته‌ها بسته به ابزار ممکن است از یکشنبه تا شنبه یا از دوشنبه تا یکشنبه باشند. ۱ ژانویه همیشه در هفته ۱ است، بدون استثنا.

در ادامه این راهنما، «شماره هفته» به معنای ISO 8601 است مگر اینکه خلاف آن ذکر شود. اگر شماره هفته از ابزاری به سبک آمریکایی (مانند WEEKNUM پیش‌فرض اکسل) دریافت کرده‌اید، فرمول تبدیل متفاوت است — به بخش پایین مراجعه کنید.

همچنین به سال نیاز دارید. «هفته ۲۳» بدون آن بی‌معناست. همیشه شماره هفته را به صورت جفت (سال، هفته) در نظر بگیرید. هفته ۲۳ سال ۲۰۲۵ از ۲ ژوئن شروع می‌شود. هفته ۲۳ سال ۲۰۲۶ از ۱ ژوئن شروع می‌شود. هفته ۱ سال ۲۰۲۶ از ۲۹ دسامبر سال ۲۰۲۵ شروع می‌شود.

فرمول اصلی: شماره هفته ISO به دوشنبه

هر هفته ISO از دوشنبه شروع می‌شود. برای یافتن دوشنبه هفته ISO شماره W در سال Y:

دوشنبه = ۴ ژانویه سال Y + (W - 1) × ۷ روز - روز هفته(۴ ژانویه سال Y) + 1

استدلال: ۴ ژانویه همیشه در هفته ISO ۱ است (طبق تعریف — در چهار روز اول سال است که وجود پنجشنبه در آن هفته را تضمین می‌کند). دوشنبه هفته‌ای که ۴ ژانویه در آن قرار دارد را پیدا کنید، سپس (W - 1) هفته به جلو بروید.

معادل ساده‌تر:

دوشنبه W1 = ۴ ژانویه سال Y - روز هفته(۴ ژانویه سال Y) + 1
دوشنبه W  = دوشنبه W1 + (W - 1) × ۷

جایی که روز هفته برای دوشنبه ۱ و برای یکشنبه ۷ برمی‌گرداند (شماره‌گذاری روز هفته ISO).

مثال: هفته ۲۳ سال ۲۰۲۶

  • ۴ ژانویه ۲۰۲۶ یکشنبه است. روز هفته ISO = ۷.
  • دوشنبه W1: ۴ ژانویه − ۷ + ۱ = ۲۹ دسامبر ۲۰۲۵.
  • دوشنبه W23: ۲۹ دسامبر ۲۰۲۵ + ۲۲ × ۷ = ۲۹ دسامبر + ۱۵۴ روز = ۱ ژوئن ۲۰۲۶.
  • یکشنبه W23: ۱ ژوئن + ۶ = ۷ ژوئن ۲۰۲۶.

هفته ۲۳ سال ۲۰۲۶ از ۱ ژوئن (دوشنبه) تا ۷ ژوئن (یکشنبه) است.

تله مرز سال

رایج‌ترین اشتباه: فرض اینکه هفته ۱ سال Y همیشه در سال Y شروع می‌شود.

اینطور نیست.

هفته ۱ سال، هفته‌ای است که اولین پنجشنبه را در بر می‌گیرد. اگر آن پنجشنبه در اوایل ژانویه باشد، دوشنبه هفته ۱ می‌تواند در دسامبر سال قبل باشد.

مثال‌ها:

هفته ISOسالدوشنبهیکشنبه
W1۲۰۲۵۳۰ دسامبر ۲۰۲۴۵ ژانویه ۲۰۲۵
W1۲۰۲۶۲۹ دسامبر ۲۰۲۵۴ ژانویه ۲۰۲۶
W1۲۰۲۷۴ ژانویه ۲۰۲۷۱۰ ژانویه ۲۰۲۷
W1۲۰۲۸۳ ژانویه ۲۰۲۸۹ ژانویه ۲۰۲۸

W1 سال ۲۰۲۵ در دسامبر ۲۰۲۴ شروع می‌شود. W1 سال ۲۰۲۶ در دسامبر ۲۰۲۵ شروع می‌شود.

این یعنی:

  • ۲۹-۳۱ دسامبر ۲۰۲۵ در هفته ISO ۱ سال ۲۰۲۶ هستند، نه ۲۰۲۵.
  • اگر کسی می‌گوید «تا W1 2026 تحویل بده»، مهلت هفته‌ای است که از ۲۹ دسامبر ۲۰۲۵ شروع می‌شود.

تله معکوس هم وجود دارد: آخرین روزهای برخی سال‌ها در هفته ۱ سال بعد قرار دارند، نه آخرین هفته سال جاری. همیشه از سال هفته ISO (کد فرمت %G در پایتون، isoyear در PostgreSQL) هنگام برچسب‌گذاری یک هفته استفاده کنید — نه سال تقویمی.

بازه کامل تاریخ برای هر شماره هفته

وقتی دوشنبه را داشتید، بقیه هفته ساده است:

روزفاصله از دوشنبه
دوشنبه
سه‌شنبه
چهارشنبه
پنجشنبه
جمعه
شنبه
یکشنبه

بازه تاریخ برای هفته W: [دوشنبه، دوشنبه + ۶ روز].

برای اهداف روزهای کاری (فقط دوشنبه تا جمعه): [دوشنبه، دوشنبه + ۴ روز].

پایتون

from datetime import date, timedelta

def iso_week_to_monday(year: int, week: int) -> date:
    # ۴ ژانویه همیشه در هفته ISO ۱ است
    jan4 = date(year, 1, 4)
    # به دوشنبه آن هفته برگرد
    week1_monday = jan4 - timedelta(days=jan4.weekday())
    # به هفته هدف برو
    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

# مثال‌ها
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  ← توجه: در ۲۰۲۵ شروع می‌شود
print(sunday)   # 2026-01-04

پایتون همچنین یک تابع داخلی برای معکوس (تاریخ به هفته ISO) دارد:

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

از d.isocalendar().year (نه d.year) هنگامی که به سال ISO نیاز دارید استفاده کنید — در مرزهای سال متفاوت هستند.

برای جستجوی معکوس با استفاده از fromisocalendar (پایتون ۳.۸+):

# دوشنبه هفته ISO ۲۳ سال ۲۰۲۶ را مستقیماً بگیر
monday = date.fromisocalendar(2026, 23, 1)  # روز هفته ۱ = دوشنبه
print(monday)  # 2026-06-01

date.fromisocalendar(year, week, weekday) ساده‌ترین رویکرد است اگر روی پایتون ۳.۸ یا بالاتر هستید.

جاوااسکریپت

جاوااسکریپت پشتیبانی بومی از هفته ISO ندارد. پیاده‌سازی دستی:

function isoWeekToMonday(year, week) {
  // ۴ ژانویه همیشه در هفته ISO ۱ است
  const jan4 = new Date(year, 0, 4)
  const dayOfWeek = jan4.getDay() || 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 }
}

// مثال‌ها
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:

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

function isoWeekToRange(year, week) {
  let d = new Date(year, 0, 4)  // هر تاریخی در سال هدف
  d = setISOWeekYear(d, year)
  d = setISOWeek(d, week)
  return {
    monday: startOfISOWeek(d),
    sunday: endOfISOWeek(d)
  }
}

date-fns تمام موارد لبه را به درستی مدیریت می‌کند و رویکرد توصیه‌شده برای کد تولیدی است.

اکسل و Google Sheets

اکسل تابع مستقیم «شماره هفته به تاریخ» ندارد، اما می‌توانید آن را با یک فرمول بسازید.

دوشنبه هفته ISO شماره W در سال Y:

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

توضیح:

  • DATE(Y,1,4) — ۴ ژانویه سال
  • WEEKDAY(DATE(Y,1,4),2) — روز هفته که دوشنبه=۱ و یکشنبه=۷
  • تفریق دوشنبه هفته ۱ را می‌دهد
  • افزودن (W-1)*7 به هفته هدف می‌رود

برای بازه کامل، یکشنبه به سادگی:

=فرمول_دوشنبه + 6

مثال در یک جدول (که A1 = سال، B1 = شماره هفته):

دوشنبه: =DATE(A1,1,4) - WEEKDAY(DATE(A1,1,4),2) + 1 + (B1-1)*7
یکشنبه: =سلول_دوشنبه + 6

هر دو سلول را به عنوان تاریخ فرمت کنید. برای سال ۲۰۲۶، هفته ۱، این فرمول ۲۹ دسامبر ۲۰۲۵ برای دوشنبه برمی‌گرداند — که درست است.

معکوس (تاریخ به شماره هفته ISO): از ISOWEEKNUM(date) استفاده کنید. برای سال ISO از راه‌حل جایگزین مقاله ISOWEEKNUM استفاده کنید، چون اکسل تابع بومی سال ISO ندارد.

SQL

PostgreSQL کامل‌ترین پشتیبانی ISO را دارد:

-- دوشنبه هفته ISO شماره ۲۳ سال ۲۰۲۶
SELECT
  make_date(2026, 1, 4)
    + (23 - 1) * 7  -- به هفته ۲۳ برو
    - EXTRACT(isodow FROM make_date(2026, 1, 4))::int + 1
    AS week_monday;
-- 2026-06-01

-- یا با استفاده از generate_series برای جستجوی بازه
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;

رویکرد ساده‌تر با استفاده از to_date در PostgreSQL با کدهای فرمت ISO:

-- تبدیل سال ISO + هفته به دوشنبه
SELECT to_date('2026' || '23' || '1', 'IYYYIWid') AS monday;
-- 2026-06-01

-- فرمت: IYYY=سال ISO، IW=هفته ISO، id=روز ISO (۱=دوشنبه)

این ساده‌ترین رویکرد PostgreSQL است: یک رشته YYYYWWD بسازید و آن را با کدهای فرمت ISO تجزیه کنید.

MySQL:

-- دوشنبه هفته ISO ۲۳ سال ۲۰۲۶
SELECT STR_TO_DATE('202623 Monday', '%X%V %W');
-- 2026-06-01

-- یا مبتنی بر گام:
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:

-- دوشنبه هفته ISO ۲۳ سال ۲۰۲۶
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

شماره هفته به سبک آمریکایی به تاریخ

اگر شماره هفته از یک سیستم آمریکایی (هفته ۱ = شامل ۱ ژانویه، هفته‌ها از یکشنبه یا دوشنبه شروع می‌شوند) آمده، فرمول ساده‌تر است چون مشکل مرز سال وجود ندارد:

شروع هفته (مبتنی بر یکشنبه):

شروع_هفته = DATE(Y, 1, 1) + (W - 1) × ۷ - WEEKDAY(DATE(Y, 1, 1), 1)

جایی که WEEKDAY برای یکشنبه ۱ و برای شنبه ۷ برمی‌گرداند.

اما شماره‌های هفته آمریکایی در برنامه‌ریزی و لجستیک بسیار کمتر از ISO رایج هستند. اگر کسی بدون مشخص کردن سیستم شماره هفته به شما داد، ISO را فرض کنید — به‌ویژه در زمینه‌های تجاری بین‌المللی یا اروپایی.

مرجع سریع ۲۰۲۶: هفته‌های ISO ۱ تا ۱۰ و ۴۸ تا ۵۳

هفته ISOسالدوشنبهیکشنبه
W1۲۰۲۶۲۹ دسامبر ۲۰۲۵۴ ژانویه ۲۰۲۶
W2۲۰۲۶۵ ژانویه ۲۰۲۶۱۱ ژانویه ۲۰۲۶
W3۲۰۲۶۱۲ ژانویه ۲۰۲۶۱۸ ژانویه ۲۰۲۶
W4۲۰۲۶۱۹ ژانویه ۲۰۲۶۲۵ ژانویه ۲۰۲۶
W5۲۰۲۶۲۶ ژانویه ۲۰۲۶۱ فوریه ۲۰۲۶
W6۲۰۲۶۲ فوریه ۲۰۲۶۸ فوریه ۲۰۲۶
W7۲۰۲۶۹ فوریه ۲۰۲۶۱۵ فوریه ۲۰۲۶
W8۲۰۲۶۱۶ فوریه ۲۰۲۶۲۲ فوریه ۲۰۲۶
W9۲۰۲۶۲۳ فوریه ۲۰۲۶۱ مارس ۲۰۲۶
W10۲۰۲۶۲ مارس ۲۰۲۶۸ مارس ۲۰۲۶
...
W48۲۰۲۶۲۳ نوامبر ۲۰۲۶۲۹ نوامبر ۲۰۲۶
W49۲۰۲۶۳۰ نوامبر ۲۰۲۶۶ دسامبر ۲۰۲۶
W50۲۰۲۶۷ دسامبر ۲۰۲۶۱۳ دسامبر ۲۰۲۶
W51۲۰۲۶۱۴ دسامبر ۲۰۲۶۲۰ دسامبر ۲۰۲۶
W52۲۰۲۶۲۱ دسامبر ۲۰۲۶۲۷ دسامبر ۲۰۲۶
W53۲۰۲۶۲۸ دسامبر ۲۰۲۶۳ ژانویه ۲۰۲۷

توجه کنید W1 سال ۲۰۲۶ از ۲۹ دسامبر ۲۰۲۵ شروع می‌شود. توجه کنید W53 سال ۲۰۲۶ در ۳ ژانویه ۲۰۲۷ پایان می‌یابد — ۲۰۲۶ یک سال ۵۳ هفته‌ای است.

خلاصه اشتباهات رایج

درج نکردن سال. «هفته ۸» مبهم است. همیشه از فرمت 2026-W08 یا معادل آن استفاده کنید.

استفاده از سال تقویمی به جای سال هفته ISO. ۲۹ دسامبر ۲۰۲۵ در هفته ISO ۱ سال ۲۰۲۶ است، نه ۲۰۲۵. ذخیره آن زیر ۲۰۲۵ آن را در دسته اشتباه قرار می‌دهد.

فرض اینکه هفته ۱ از ۱ ژانویه شروع می‌شود. در بسیاری از سال‌ها از ۲۹، ۳۰ یا ۳۱ دسامبر شروع می‌شود. اگر نیاز دارید ۱ ژانویه همیشه در هفته ۱ باشد، از سیستم آمریکایی استفاده می‌کنید، نه ISO.

خطای یک واحد در فرمول دوشنبه. لنگر ۴ ژانویه مهم است — نه ۱ ژانویه (که ممکن است در آخرین هفته سال قبل باشد). استفاده از ۱ ژانویه به عنوان لنگر در سال‌هایی که ۱ ژانویه دیر در هفته می‌افتد نتایج اشتباه می‌دهد.

عدم آزمایش تاریخ‌های مرز سال. هر کد مدیریت تاریخ باید با ۲۸-۳۱ دسامبر و ۱-۴ ژانویه آزمایش شود. این چهار تا هفت روز جایی است که تمام موارد لبه زندگی می‌کنند.

از ماشین‌حساب شماره هفته ISO برای جستجوی بازه تاریخ هر شماره هفته استفاده کنید، یا شماره هفته جاری و بازه تاریخ هفته ISO امروز را بررسی کنید.