如何让JS/PHP获取英国时区、周日起始的周数?
英国时区周日起始的周数计算方案
问题背景
我需要获取以周日为起始、基于英国时区的周数,但目前国际用户访问网站时,会因为时区差异得到不同的周数。
当前使用的JavaScript代码如下:
Date.prototype.getWeek = function() { var d = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate())); d.setUTCDate(d.getUTCDate() - d.getUTCDay()); var yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1)); return Math.ceil((((d - yearStart) / 86400000) + 1) / 7); }; function getWeekNum(dateStr) { var date = new Date(dateStr); var currentWeekNumber = date.getWeek(); return currentWeekNumber; } console.log(getWeekNum("2023-03-19"));
英国与坎昆的周数差异对比:
核心问题:如何强制使用英国时区计算周数?若JavaScript无法实现,能否提供PHP版本的实现?
JavaScript实现方案
要强制基于英国时区(Europe/London)计算周日起始的周数,可借助Intl.DateTimeFormat处理时区转换,确保所有计算逻辑基于英国本地时间:
function getUKWeekNumber(dateStr) { // 初始化英国时区格式化器 const ukFormatter = new Intl.DateTimeFormat('en-GB', { timeZone: 'Europe/London', year: 'numeric', month: '2-digit', day: '2-digit' }); // 提取英国时区下的年、月、日 const dateParts = ukFormatter.formatToParts(new Date(dateStr)); const ukYear = dateParts.find(p => p.type === 'year').value; const ukMonth = dateParts.find(p => p.type === 'month').value; const ukDay = dateParts.find(p => p.type === 'day').value; // 创建英国本地日期对象 const ukLocalDate = new Date(`${ukYear}-${ukMonth}-${ukDay}`); // 定位到当前日期所在周的周日(getDay()返回0代表周日) const weekStart = new Date(ukLocalDate); weekStart.setDate(weekStart.getDate() - weekStart.getDay()); // 定位到英国时区当年的第一个周日 const yearStart = new Date(`${ukYear}-01-01`); const firstWeekSunday = new Date(yearStart); firstWeekSunday.setDate(firstWeekSunday.getDate() - firstWeekSunday.getDay()); // 如果当年1月1日是周日之后的日期,第一周起始要往前推一周 if (firstWeekSunday > yearStart) { firstWeekSunday.setDate(firstWeekSunday.getDate() - 7); } // 计算周数 const dayDiff = Math.floor((weekStart - firstWeekSunday) / (1000 * 60 * 60 * 24)); return Math.floor(dayDiff / 7) + 1; } // 测试用例 console.log(getUKWeekNumber("2023-03-19"));
关键说明
- 用
Intl.DateTimeFormat确保提取的日期是英国本地时间,自动适配夏令时 - 基于英国本地日期计算周日起始,避免UTC转换带来的时区偏差
- 统一以英国时区当年第一个周日作为第一周的起始点
PHP实现方案
PHP的DateTime类原生支持时区指定,实现起来更简洁:
function getUKWeekNumber(string $dateStr): int { // 创建英国时区的日期对象 $timezone = new DateTimeZone('Europe/London'); $targetDate = DateTime::createFromFormat('Y-m-d', $dateStr, $timezone); // 获取目标日期所在周的周日(如果当天是周日则不调整) $weekStart = clone $targetDate; $weekStart->modify('last Sunday'); if ($weekStart > $targetDate) { $weekStart->modify('-7 days'); } // 获取当年的第一个周日 $yearStart = new DateTime($targetDate->format('Y') . '-01-01', $timezone); $firstWeekSunday = clone $yearStart; $firstWeekSunday->modify('last Sunday'); if ($firstWeekSunday > $yearStart) { $firstWeekSunday->modify('-7 days'); } // 计算周数 $interval = $firstWeekSunday->diff($weekStart); return (int)($interval->days / 7) + 1; } // 测试用例 echo getUKWeekNumber("2023-03-19");
关键说明
- 直接指定
Europe/London时区,自动处理夏令时切换 - 通过
modify方法快速定位到周起始周日 - 用
diff方法计算日期差,避免时间戳计算的潜在问题
内容的提问来源于stack exchange,提问作者Richard Jacobs
相关产品推荐
相关产品推荐

