Как мне получить текущий номер недели года, как в PHP date('W')
?
Это должен быть номер недели в году по ISO-8601 , недели начинаются с понедельника.
Как мне получить текущий номер недели года, как в PHP date('W')
?
Это должен быть номер недели в году по ISO-8601 , недели начинаются с понедельника.
Ответы:
Вы можете получить то, что хотите здесь: http://www.merlyn.demon.co.uk/js-date6.htm#YWD .
Лучшая ссылка на том же сайте: Работа с неделями .
Вот код, основанный на предоставленных ссылках и опубликованных ранее Dommer. Он был слегка протестирован против результатов на http://www.merlyn.demon.co.uk/js-date6.htm#YWD . Пожалуйста, проверьте внимательно, никаких гарантий не предоставляется.
Возникла проблема с датами в период перехода на летнее время и годами, когда 1 января было пятницей. Исправлено с использованием всех методов UTC. Следующее возвращает идентичные результаты в Moment.js.
/* 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];
}
var result = getWeekNumber(new Date());
document.write('It\'s currently week ' + result[1] + ' of ' + result[0]);
Часы обнуляются при создании даты "UTC".
Минимальная версия прототипа (возвращает только номер недели):
Date.prototype.getWeekNumber = function(){
var d = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate()));
var dayNum = d.getUTCDay() || 7;
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
return Math.ceil((((d - yearStart) / 86400000) + 1)/7)
};
document.write('The current ISO week number is ' + new Date().getWeekNumber());
В этом разделе вы можете ввести любую дату в формате ГГГГ-ММ-ДД и убедиться, что этот код дает тот же номер недели, что и номер недели Moment.js ISO (проверено более 50 лет с 2000 по 2050 год).
Date.prototype.getWeekNumber = function(){
var d = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate()));
var dayNum = d.getUTCDay() || 7;
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
return Math.ceil((((d - yearStart) / 86400000) + 1)/7)
};
function checkWeek() {
var s = document.getElementById('dString').value;
var m = moment(s, 'YYYY-MM-DD');
document.getElementById('momentWeek').value = m.format('W');
document.getElementById('answerWeek').value = m.toDate().getWeekNumber();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
Enter date YYYY-MM-DD: <input id="dString" value="2021-02-22">
<button onclick="checkWeek(this)">Check week number</button><br>
Moment: <input id="momentWeek" readonly><br>
Answer: <input id="answerWeek" readonly>
d.setMilliseconds(0)
- он продолжал показывать разные номера недель для одной и той же даты в зависимости от того, использовал ли я новую дату () или новую дату («1/4/2016»). Просто предупреждение для других, кто может испытать то же самое.
Не номер недели ISO-8601, но если поисковая система все равно указала вам сюда.
Как сказано выше, но без класса:
let now = new Date();
let onejan = new Date(now.getFullYear(), 0, 1);
let week = Math.ceil( (((now.getTime() - onejan.getTime()) / 86400000) + onejan.getDay() + 1) / 7 );
(now.getTime() - onejan.getTime())
чтобы избежать проблем со сборкой.
Соответственно http://javascript.about.com/library/blweekyear.htm
Date.prototype.getWeek = function() {
var onejan = new Date(this.getFullYear(),0,1);
var millisecsInDay = 86400000;
return Math.ceil((((this - onejan) /millisecsInDay) + onejan.getDay()+1)/7);
};
Date.format()
Библиотека Джейкоба Райта реализует форматирование даты в стиле функции PHP date()
и поддерживает номер недели ISO-8601:
new Date().format('W');
Это может быть немного излишним для всего номера недели, но он поддерживает форматирование в стиле PHP и очень удобен, если вы будете делать это много.
getWeekOfYear: function(date) {
var target = new Date(date.valueOf()),
dayNumber = (date.getUTCDay() + 6) % 7,
firstThursday;
target.setUTCDate(target.getUTCDate() - dayNumber + 3);
firstThursday = target.valueOf();
target.setUTCMonth(0, 1);
if (target.getUTCDay() !== 4) {
target.setUTCMonth(0, 1 + ((4 - target.getUTCDay()) + 7) % 7);
}
return Math.ceil((firstThursday - target) / (7 * 24 * 3600 * 1000)) + 1;
}
Следующий код не зависит от часового пояса (используются даты в формате UTC) и работает в соответствии с https://en.wikipedia.org/wiki/ISO_8601
Я нашел полезным класс Java SE SimpleDateFormat, описанный в спецификации Oracle: http://goo.gl/7MbCh5 . В моем случае в Google Apps Script это работало так:
function getWeekNumber() {
var weekNum = parseInt(Utilities.formatDate(new Date(), "GMT", "w"));
Logger.log(weekNum);
}
Например, в макросе электронной таблицы вы можете получить фактический часовой пояс файла:
function getWeekNumber() {
var weekNum = parseInt(Utilities.formatDate(new Date(), SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(), "w"));
Logger.log(weekNum);
}
Это добавляет метод getWeek к Date.prototype, который возвращает номер недели с начала года. Аргумент определяет, какой день недели считать первым. Если аргумент не передан, первым днем считается воскресенье.
/**
* Get week number in the year.
* @param {Integer} [weekStart=0] First day of the week. 0-based. 0 for Sunday, 6 for Saturday.
* @return {Integer} 0-based number of week.
*/
Date.prototype.getWeek = function(weekStart) {
var januaryFirst = new Date(this.getFullYear(), 0, 1);
if(weekStart !== undefined && (typeof weekStart !== 'number' || weekStart % 1 !== 0 || weekStart < 0 || weekStart > 6)) {
throw new Error('Wrong argument. Must be an integer between 0 and 6.');
}
weekStart = weekStart || 0;
return Math.floor((((this - januaryFirst) / 86400000) + januaryFirst.getDay() - weekStart) / 7);
};
new Date(Date.UTC(2018,11, 31)).getWeek(1)+1
(понедельник - первый день недели в Германии).
Получить номер недели любой заданной даты
function week(year,month,day) {
function serial(days) { return 86400000*days; }
function dateserial(year,month,day) { return (new Date(year,month-1,day).valueOf()); }
function weekday(date) { return (new Date(date)).getDay()+1; }
function yearserial(date) { return (new Date(date)).getFullYear(); }
var date = year instanceof Date ? year.valueOf() : typeof year === "string" ? new Date(year).valueOf() : dateserial(year,month,day),
date2 = dateserial(yearserial(date - serial(weekday(date-serial(1))) + serial(4)),1,3);
return ~~((date - date2 + serial(weekday(date2) + 5))/ serial(7));
}
console.log(
week(2016, 06, 11),//23
week(2015, 9, 26),//39
week(2016, 1, 1),//53
week(2016, 1, 4),//1
week(new Date(2016, 0, 4)),//1
week("11 january 2016")//2
);
I need the week to begin on a Sunday
; Я думаю, что единственное необходимое изменение - это заменить функцию weekday () .getDay()+1
на.getDay()
Код ниже вычисляет правильный номер недели по ISO 8601. Он соответствует PHP date("W")
за каждую неделю между 01.01.1970 и 01.01.21.
/**
* Get the ISO week date week number
*/
Date.prototype.getWeek = function () {
// Create a copy of this date object
var target = new Date(this.valueOf());
// ISO week date weeks start on Monday, so correct the day number
var dayNr = (this.getDay() + 6) % 7;
// ISO 8601 states that week 1 is the week with the first Thursday of that year
// Set the target date to the Thursday in the target week
target.setDate(target.getDate() - dayNr + 3);
// Store the millisecond value of the target date
var firstThursday = target.valueOf();
// Set the target to the first Thursday of the year
// First, set the target to January 1st
target.setMonth(0, 1);
// Not a Thursday? Correct the date to the next Thursday
if (target.getDay() !== 4) {
target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);
}
// The week number is the number of weeks between the first Thursday of the year
// and the Thursday in the target week (604800000 = 7 * 24 * 3600 * 1000)
return 1 + Math.ceil((firstThursday - target) / 604800000);
}
Источник: Тако ван ден Брук
Если вы не занимаетесь расширением прототипов, то вот функция:
function getWeek(date) {
if (!(date instanceof Date)) date = new Date();
// ISO week date weeks start on Monday, so correct the day number
var nDay = (date.getDay() + 6) % 7;
// ISO 8601 states that week 1 is the week with the first Thursday of that year
// Set the target date to the Thursday in the target week
date.setDate(date.getDate() - nDay + 3);
// Store the millisecond value of the target date
var n1stThursday = date.valueOf();
// Set the target to the first Thursday of the year
// First, set the target to January 1st
date.setMonth(0, 1);
// Not a Thursday? Correct the date to the next Thursday
if (date.getDay() !== 4) {
date.setMonth(0, 1 + ((4 - date.getDay()) + 7) % 7);
}
// The week number is the number of weeks between the first Thursday of the year
// and the Thursday in the target week (604800000 = 7 * 24 * 3600 * 1000)
return 1 + Math.ceil((n1stThursday - date) / 604800000);
}
Пример использования:
getWeek(); // Returns 37 (or whatever the current week is)
getWeek(new Date('Jan 2, 2011')); // Returns 52
getWeek(new Date('Jan 1, 2016')); // Returns 53
getWeek(new Date('Jan 4, 2016')); // Returns 1
+6 ) % 7
делает эта часть. Спасибо от скраба!
javascript date = date instanceof Date ? new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) : new Date()
Если вы уже участвуете в проекте Angular, вы можете использовать $filter('date')
.
Например:
var myDate = new Date();
var myWeek = $filter('date')(myDate, 'ww');
Фрагмент кода, который мне очень нравится, выглядит следующим образом:
var yearStart = +new Date(d.getFullYear(), 0, 1);
var today = +new Date(d.getFullYear(),d.getMonth(),d.getDate());
var dayOfYear = ((today - yearStart + 1) / 86400000);
return Math.ceil(dayOfYear / 7).toString();
Примечание:
d
это моя дата, для которой мне нужен номер текущей недели.
В +
обращенных даты в числа (работа с машинописью).
С Luxon ( https://github.com/moment/luxon ):
import { DateTime } from 'luxon';
const week: number = DateTime.fromJSDate(new Date()).weekNumber;
fromJSDate()
только один из многих. Luxon был создан одним из разработчиков MomentJS, и ожидается, что он будет поддерживаться неограниченное время. На данный момент это или Момент - действительно лучший способ выполнить эту задачу.
Вот моя реализация для расчета номера недели в JavaScript. исправлены также смещения летнего и зимнего времени. Я использовал определение недели из этой статьи: ISO 8601
Недели с понедельника по воскресенье, а 4 января всегда бывает первой неделей года.
// add get week prototype functions
// weeks always start from monday to sunday
// january 4th is always in the first week of the year
Date.prototype.getWeek = function () {
year = this.getFullYear();
var currentDotw = this.getWeekDay();
if (this.getMonth() == 11 && this.getDate() - currentDotw > 28) {
// if true, the week is part of next year
return this.getWeekForYear(year + 1);
}
if (this.getMonth() == 0 && this.getDate() + 6 - currentDotw < 4) {
// if true, the week is part of previous year
return this.getWeekForYear(year - 1);
}
return this.getWeekForYear(year);
}
// returns a zero based day, where monday = 0
// all weeks start with monday
Date.prototype.getWeekDay = function () {
return (this.getDay() + 6) % 7;
}
// corrected for summer/winter time
Date.prototype.getWeekForYear = function (year) {
var currentDotw = this.getWeekDay();
var fourjan = new Date(year, 0, 4);
var firstDotw = fourjan.getWeekDay();
var dayTotal = this.getDaysDifferenceCorrected(fourjan) // the difference in days between the two dates.
// correct for the days of the week
dayTotal += firstDotw; // the difference between the current date and the first monday of the first week,
dayTotal -= currentDotw; // the difference between the first monday and the current week's monday
// day total should be a multiple of 7 now
var weeknumber = dayTotal / 7 + 1; // add one since it gives a zero based week number.
return weeknumber;
}
// corrected for timezones and offset
Date.prototype.getDaysDifferenceCorrected = function (other) {
var millisecondsDifference = (this - other);
// correct for offset difference. offsets are in minutes, the difference is in milliseconds
millisecondsDifference += (other.getTimezoneOffset()- this.getTimezoneOffset()) * 60000;
// return day total. 1 day is 86400000 milliseconds, floor the value to return only full days
return Math.floor(millisecondsDifference / 86400000);
}
для тестирования я использовал следующие тесты JavaScript в Qunit
var runweekcompare = function(result, expected) {
equal(result, expected,'Week nr expected value: ' + expected + ' Actual value: ' + result);
}
test('first week number test', function () {
expect(5);
var temp = new Date(2016, 0, 4); // is the monday of the first week of the year
runweekcompare(temp.getWeek(), 1);
var temp = new Date(2016, 0, 4, 23, 50); // is the monday of the first week of the year
runweekcompare(temp.getWeek(), 1);
var temp = new Date(2016, 0, 10, 23, 50); // is the sunday of the first week of the year
runweekcompare(temp.getWeek(), 1);
var temp = new Date(2016, 0, 11, 23, 50); // is the second week of the year
runweekcompare(temp.getWeek(), 2);
var temp = new Date(2016, 1, 29, 23, 50); // is the 9th week of the year
runweekcompare(temp.getWeek(), 9);
});
test('first day is part of last years last week', function () {
expect(2);
var temp = new Date(2016, 0, 1, 23, 50); // is the first last week of the previous year
runweekcompare(temp.getWeek(), 53);
var temp = new Date(2011, 0, 2, 23, 50); // is the first last week of the previous year
runweekcompare(temp.getWeek(), 52);
});
test('last day is part of next years first week', function () {
var temp = new Date(2013, 11, 30); // is part of the first week of 2014
runweekcompare(temp.getWeek(), 1);
});
test('summer winter time change', function () {
expect(2);
var temp = new Date(2000, 2, 26);
runweekcompare(temp.getWeek(), 12);
var temp = new Date(2000, 2, 27);
runweekcompare(temp.getWeek(), 13);
});
test('full 20 year test', function () {
//expect(20 * 12 * 28 * 2);
for (i = 2000; i < 2020; i++) {
for (month = 0; month < 12; month++) {
for (day = 1; day < 29 ; day++) {
var temp = new Date(i, month, day);
var expectedweek = temp.getWeek();
var temp2 = new Date(i, month, day, 23, 50);
var resultweek = temp.getWeek();
equal(expectedweek, Math.round(expectedweek), 'week number whole number expected ' + Math.round(expectedweek) + ' resulted week nr ' + expectedweek);
equal(resultweek, expectedweek, 'Week nr expected value: ' + expectedweek + ' Actual value: ' + resultweek + ' for year ' + i + ' month ' + month + ' day ' + day);
}
}
}
});
Номер этой недели был настоящей головной болью. Большинство скриптов в сети у меня не работали. Они работали большую часть времени, но все они в какой-то момент ломались, особенно когда изменился год, и последняя неделя года внезапно стала первой неделей следующего года и т. Д. Даже фильтр даты Angular показал неверные данные (это была 1-я неделя следующего года, angular дал неделя 53).
Заметка: Примеры предназначены для работы с европейскими неделями (сначала понедельник)!
getWeek ()
Date.prototype.getWeek = function(){
// current week's Thursday
var curWeek = new Date(this.getTime());
curWeek.setDay(4);
// Get year's first week's Thursday
var firstWeek = new Date(curWeek.getFullYear(), 0, 4);
firstWeek.setDay(4);
return (curWeek.getDayIndex() - firstWeek.getDayIndex()) / 7 + 1;
};
setDay ()
/**
* Make a setDay() prototype for Date
* Sets week day for the date
*/
Date.prototype.setDay = function(day){
// Get day and make Sunday to 7
var weekDay = this.getDay() || 7;
var distance = day - weekDay;
this.setDate(this.getDate() + distance);
return this;
}
getDayIndex ()
/*
* Returns index of given date (from Jan 1st)
*/
Date.prototype.getDayIndex = function(){
var start = new Date(this.getFullYear(), 0, 0);
var diff = this - start;
var oneDay = 86400000;
return Math.floor(diff / oneDay);
};
Я протестировал это, и, похоже, он работает очень хорошо, но если вы заметите в нем недостаток, сообщите мне.
Я много пытался получить самый короткий код, чтобы получить номер недели в соответствии с ISO.
Date.prototype.getWeek=function(){
var date=new Date(this);
date.setHours(0,0,0,0);
return Math.round(((date.setDate(this.getDate()+2-(this.getDay()||7))-date.setMonth(0,4))/8.64e7+3+(date.getDay()||7))/7)+"/"+date.getFullYear();}
Переменная date
необходима, чтобы избежать изменения оригинала this
. Я использовал возвращаемые значения setDate()
и, setMonth()
чтобы обойтись без них, getTime()
чтобы сохранить длину кода, и я использовал экспоненциальное число для миллисекунд дня вместо умножения отдельных элементов или числа с пятью нулями. this
- дата или количество миллисекунд, возвращаемое значение - String
например, «49/2017».
Другой вариант на основе библиотеки: используйте d3-time-format
:
const formatter = d3.timeFormat('%U');
const weekNum = formatter(new Date());
Кратчайший обходной путь для Angular2 + DatePipe с поправкой на ISO-8601:
import {DatePipe} from "@angular/common";
public rightWeekNum: number = 0;
constructor(private datePipe: DatePipe) { }
calcWeekOfTheYear(dateInput: Date) {
let falseWeekNum = parseInt(this.datePipe.transform(dateInput, 'ww'));
this.rightWeekNum = (dateInput.getDay() == 0) ? falseWeekNumber-1 : falseWeekNumber;
}
now = new Date();
today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
firstOfYear = new Date(now.getFullYear(), 0, 1);
numOfWeek = Math.ceil((((today - firstOfYear) / 86400000)-1)/7);