我构建了一个日历控件,并添加了周数字作为最后一步,但在SO和SO之外,我能找到的每个脚本示例都遇到了问题(其中大多数都是从另一个脚本中复制过来的)。
问题是,当日期落在部分月份时,周计算似乎变得混乱,当它是新月中的同一周时,要么继续计数,要么认为上个月的最后一个完整周与下个月的第一个完整新周相同。
以下是其中一个库的可视化演示(它们都有自己的不准确性,因为它们通常基于固定的数字来计算周,并从那里构建):
您可以查看codepen here,因为项目相当复杂,我在开始时使用Date.prototype.getWeek
函数可以更容易地处理这一点。请随意交换此处提供的示例中的任何代码,因为它们最终都会在几个月内崩溃。
使用的一些计算:
当运行"Get week of year in JavaScript like in PHP“中的最新示例(2017)时,现在返回的周是42。当你查看我的日历时,根据这里的https://www.epochconverter.com/weeks/2018,10月份的那一周显示为42,这是正确的。
给出这个例子,有整整几周共享相同的周数-所以我看不出42
是如何准确的。
Date.prototype.getWeek = function (dowOffset) {
/*getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.epoch-calendar.com */
dowOffset = typeof(dowOffset) == 'int' ? dowOffset : 0; //default dowOffset to zero
var newYear = new Date(this.getFullYear(),0,1);
var day = newYear.getDay() - dowOffset; //the day of week the year begins on
day = (day >= 0 ? day : day + 7);
var daynum = Math.floor((this.getTime() - newYear.getTime() -
(this.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/86400000) + 1;
var weeknum;
//if the year starts before the middle of a week
if(day < 4) {
weeknum = Math.floor((daynum+day-1)/7) + 1;
if(weeknum > 52) {
nYear = new Date(this.getFullYear() + 1,0,1);
nday = nYear.getDay() - dowOffset;
nday = nday >= 0 ? nday : nday + 7;
/*if the next year starts before the middle of
the week, it is week #1 of that year*/
weeknum = nday < 4 ? 1 : 53;
}
}
else {
weeknum = Math.floor((daynum+day-1)/7);
}
return weeknum;
};
Here is some code (也尝试过这个),这是特定于周日的(见底部附近)。我还在这里粘贴了相关的片段:
/* For a given date, get the ISO week number
*
* Based on information at:
*
* http://www.merlyn.demon.co.uk/weekcalc.htm#WNR
*
* Algorithm is to find nearest thursday, it's year
* is the year of the week number. Then get weeks
* between that date and the first day of that year.
*
* Note that dates in one year can be weeks of previous
* or next year, overlap is up to 3 days.
*
* e.g. 2014/12/29 is Monday in week 1 of 2015
* 2012/1/1 is Sunday in week 52 of 2011
*/
function getWeekNumber(d) {
// Copy date so don't modify original
d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
// Set to nearest Thursday: current date + 4 - current day number
// Make Sunday's day number 7
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay()||7));
// Get first day of year
var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
// Calculate full weeks to nearest Thursday
var weekNo = Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7);
// Return array of year and week number
return [d.getUTCFullYear(), weekNo];
}
发布于 2018-10-20 21:06:40
算法是使用下一个星期六的星期数。因此,获取下一个星期六,然后使用它的年份作为1月1日。如果不是星期天,则转到前一个星期天。然后从那里得到周数。这听起来可能有点复杂,但它只有几行代码。下面的大部分都是用于游戏的辅助工具。
希望注释足够,getWeekNumber将返回一个[year, weekNumber]
数组。针对Mac OS X日历进行了测试,该日历似乎使用了相同的星期编号。请彻底测试,特别是在夏令时转换前后。
/* Get week number in year based on:
* - week starts on Sunday
* - week number and year is that of the next Saturday,
* or current date if it's Saturday
* 1st week of 2011 starts on Sunday 26 December, 2010
* 1st week of 2017 starts on Sunday 1 January, 2017
*
* Calculations use UTC to avoid daylight saving issues.
*
* @param {Date} date - date to get week number of
* @returns {number[]} year and week number
*/
function getWeekNumber(date) {
// Copy date as UTC to avoid DST
var d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
// Shift to the following Saturday to get the year
d.setUTCDate(d.getUTCDate() + 6 - d.getUTCDay());
// Get the first day of the year
var yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
yearStart.setUTCDate(yearStart.getUTCDate() - yearStart.getUTCDay());
// Get difference between yearStart and d in milliseconds
// Reduce to whole weeks
return [d.getUTCFullYear(), (Math.ceil((d - yearStart) / 6.048e8))];
}
// Helper to format dates
function fDate(d) {
var opts = {weekday:'short',month:'short',day:'numeric',year:'numeric'};
return d.toLocaleString(undefined, opts);
}
// Parse yyyy-mm-dd as local
function pDate(s){
var b = (s+'').split(/\D/);
var d = new Date(b[0],b[1]-1,b[2]);
return d.getMonth() == b[1]-1? d : new Date(NaN);
}
// Handle button click
function doButtonClick(){
var d = pDate(document.getElementById('inp0').value);
var span = document.getElementById('weekNumber');
if (isNaN(d)) {
span.textContent = 'Invalid date';
} else {
let [y,w] = getWeekNumber(d);
span.textContent = `${fDate(d)} is in week ${w} of ${y}`;
}
}
Date:<input id="inp0" placeholder="yyyy-mm-dd">
<button type="button" onclick="doButtonClick()">Get week number</button><br>
<span id="weekNumber"></span>
https://stackoverflow.com/questions/52904438
复制相似问题