JavaScript - obtenha o primeiro dia da semana a partir da data atual

161

Preciso da maneira mais rápida de obter o primeiro dia da semana. Por exemplo: hoje é 11 de novembro e quinta-feira; e eu quero o primeiro dia desta semana, que é 8 de novembro, e uma segunda-feira. Preciso do método mais rápido para a função de mapa do MongoDB, alguma idéia?

INs
fonte
Se cada pedacinho de velocidade for crucial, convém testar a minha resposta. Estou obtendo um desempenho um pouco melhor com o meu nos navegadores (exceto o IE, que favorece o CMS). Obviamente, você precisaria testá-lo com o MongoDB. Quando a função passa uma data que é segunda-feira, deve ser ainda mais rápida, pois retorna apenas a data original não modificada.
user113716
Eu tive o mesmo problema e porque o objeto date do javascript tem muitos erros que estou usando agora datejs.com (aqui code.google.com/p/datejs ), uma biblioteca que corrige o comportamento incorreto da data nativa.
lolol
O título da pergunta solicita o primeiro dia da semana, enquanto a descrição da pergunta solicita a data da última segunda-feira. Essas são, na verdade, duas perguntas diferentes. Verifique minha resposta que resolve os dois de maneira correta.
Louis Ameline

Respostas:

322

Usando o getDaymétodo de objetos Date, você pode saber o número do dia da semana (sendo 0 = domingo, 1 = segunda-feira etc.).

Você pode subtrair esse número de dias mais um, por exemplo:

function getMonday(d) {
  d = new Date(d);
  var day = d.getDay(),
      diff = d.getDate() - day + (day == 0 ? -6:1); // adjust when day is sunday
  return new Date(d.setDate(diff));
}

getMonday(new Date()); // Mon Nov 08 2010
CMS
fonte
3
Esta função possui um erro? - se a data em questão for quinta-feira, o dia 2, dia = 4, diff = 2 - 4 + 1 = -1, e o resultado de setDate será 'o dia antes do último dia do mês anterior' (veja isso ).
Izhaki 24/05
2
@Izhaki, o que você quer dizer? Para 2 de maio, a função retorna 29 de abril, o que está correto.
meze 26/07
14
Se o domingo for o primeiro dia da semana, use:diff = d.getDate() - day;
cfree
2
Obrigado pelo código @SMS. Fiz uma pequena reviravolta para obter exatamente 0 horas do primeiro dia da semana. d.setHours(0); d.setMinutes(0); d.setSeconds(0);
22716 Awi
3
a propósito, d.setDate é mutável, ele altera o "d" em si
Ayyash
53

Não tenho certeza de como ele se compara ao desempenho, mas isso funciona.

var today = new Date();
var day = today.getDay() || 7; // Get current day number, converting Sun. to 7
if( day !== 1 )                // Only manipulate the date if it isn't Mon.
    today.setHours(-24 * (day - 1));   // Set the hours to day number minus 1
                                         //   multiplied by negative 24
alert(today); // will be Monday

Ou como uma função:

# modifies _date_
function setToMonday( date ) {
    var day = date.getDay() || 7;  
    if( day !== 1 ) 
        date.setHours(-24 * (day - 1)); 
    return date;
}

setToMonday(new Date());
user113716
fonte
4
Essa deveria ter sido a resposta, é a única que responde à pergunta. Os outros estão com erros ou encaminhá-lo para bibliotecas de terceiros.
OverMars
Legal, funciona para mim! Ao fazer alguns ajustes, eu recebo os dois, segunda e sexta-feira da semana, a partir de uma determinada data!
alexventuraio
10
Isso é ótimo, exceto que essa função deve ser chamada "setToMonday", pois modifica o objeto de data passado. GetMonday retornaria uma nova data que é a segunda-feira com base na data de entrada. Uma diferença sutil, mas que me pegou depois de usar esta função. A correção mais fácil é colocar date = new Date(date);como a primeira linha na função getMonday.
Shane
Isso é incrível. Um método getSunday é ainda mais fácil! Muitíssimo obrigado!
JesusIsMyDriver.dll
4
Esta resposta está errada, porque nem todos os dias têm 24h por causa do horário de verão. Pode alterar a hora da sua data inesperadamente ou até retornar o dia errado em determinadas ocasiões.
Louis Ameline
13

Confira Date.js

Date.today().previous().monday()
Matt
fonte
1
ou talvezDate.parse('last monday');
Anurag
Eu preciso dele para o banco de dados MongoDB. Portanto, não posso fazer referência ao date.js, mas obrigado pelo seu snippet de código.
INs
1
Ah, eu não sabia que era possível executar JS diretamente no MongoDB. Isso é bem liso. Supunha que você estivesse usando o JS para preparar os dados da consulta.
Matt
Como o jQuery, não está interessado em abrir uma biblioteca inteira (por menor que seja) para obter acesso a uma função simples.
The Muffin Man
Não é uma boa solução, porque há países, o primeiro dia da semana é domingo.
Stefan Brendle 17/01
11

A resposta do CMS está correta, mas assume que segunda-feira é o primeiro dia da semana.
A resposta de Chandler Zwolle está correta, mas brinca com o protótipo de Data.
Outras respostas que tocam com hora / minutos / segundos / milissegundos estão incorretas.

A função abaixo está correta e assume uma data como primeiro parâmetro e o primeiro dia da semana desejado como segundo parâmetro (0 para domingo, 1 para segunda-feira etc.). Nota: a hora, minutos e segundos são definidos como 0 para ter o início do dia.

function firstDayOfWeek(dateObject, firstDayOfWeekIndex) {

    const dayOfWeek = dateObject.getDay(),
        firstDayOfWeek = new Date(dateObject),
        diff = dayOfWeek >= firstDayOfWeekIndex ?
            dayOfWeek - firstDayOfWeekIndex :
            6 - dayOfWeek

    firstDayOfWeek.setDate(dateObject.getDate() - diff)
    firstDayOfWeek.setHours(0,0,0,0)

    return firstDayOfWeek
}

// August 18th was a Saturday
let lastMonday = firstDayOfWeek(new Date('August 18, 2018 03:24:00'), 1)

// outputs something like "Mon Aug 13 2018 00:00:00 GMT+0200"
// (may vary according to your time zone)
document.write(lastMonday)

Louis Ameline
fonte
8
var dt = new Date(); // current date of week
var currentWeekDay = dt.getDay();
var lessDays = currentWeekDay == 0 ? 6 : currentWeekDay - 1;
var wkStart = new Date(new Date(dt).setDate(dt.getDate() - lessDays));
var wkEnd = new Date(new Date(wkStart).setDate(wkStart.getDate() + 6));

Isso vai funcionar bem.

Parth Shah
fonte
4

Estou usando isso

function get_next_week_start() {
   var now = new Date();
   var next_week_start = new Date(now.getFullYear(), now.getMonth(), now.getDate()+(8 - now.getDay()));
   return next_week_start;
}
1nstinct
fonte
3

Essa função usa o tempo atual de milissegundos para subtrair a semana atual e subtrai mais uma semana se a data atual estiver em uma segunda-feira (o javascript conta no domingo).

function getMonday(fromDate) {
    // length of one day i milliseconds
  var dayLength = 24 * 60 * 60 * 1000;

  // Get the current date (without time)
    var currentDate = new Date(fromDate.getFullYear(), fromDate.getMonth(), fromDate.getDate());

  // Get the current date's millisecond for this week
  var currentWeekDayMillisecond = ((currentDate.getDay()) * dayLength);

  // subtract the current date with the current date's millisecond for this week
  var monday = new Date(currentDate.getTime() - currentWeekDayMillisecond + dayLength);

  if (monday > currentDate) {
    // It is sunday, so we need to go back further
    monday = new Date(monday.getTime() - (dayLength * 7));
  }

  return monday;
}

Eu testei quando a semana se estende de um mês para outro (e também anos), e parece funcionar corretamente.

einord
fonte
3

Boa noite,

Eu prefiro ter apenas um método de extensão simples:

Date.prototype.startOfWeek = function (pStartOfWeek) {
    var mDifference = this.getDay() - pStartOfWeek;

    if (mDifference < 0) {
        mDifference += 7;
    }

    return new Date(this.addDays(mDifference * -1));
}

Você notará que isso realmente utiliza outro método de extensão que eu uso:

Date.prototype.addDays = function (pDays) {
    var mDate = new Date(this.valueOf());
    mDate.setDate(mDate.getDate() + pDays);
    return mDate;
};

Agora, se suas semanas começarem no domingo, passe um "0" para o parâmetro pStartOfWeek, assim:

var mThisSunday = new Date().startOfWeek(0);

Da mesma forma, se suas semanas começarem na segunda-feira, passe um "1" para o parâmetro pStartOfWeek:

var mThisMonday = new Date().startOfWeek(1);

Saudações,

Chandler Zwolle
fonte
2

Primeiro dia da semana

Para obter a data do primeiro dia da semana a partir de hoje, você pode usar algo como:

function getUpcomingSunday() {
  const date = new Date();
  const today = date.getDate();
  const dayOfTheWeek = date.getDay();
  const newDate = date.setDate(today - dayOfTheWeek + 7);
  return new Date(newDate);
}

console.log(getUpcomingSunday());

Ou para obter o último dia da semana a partir de hoje:

function getLastSunday() {
  const date = new Date();
  const today = date.getDate();
  const dayOfTheWeek = date.getDay();
  const newDate = date.setDate(today - (dayOfTheWeek || 7));
  return new Date(newDate);
}

console.log(getLastSunday());

* Dependendo do seu fuso horário, o início da semana não precisa começar no domingo, ele pode começar na sexta, sábado, segunda ou qualquer outro dia em que sua máquina estiver configurada. Esses métodos serão responsáveis ​​por isso.

* Você também pode formatá-lo usando o toISOStringmétodo da seguinte forma:getLastSunday().toISOString()

Lior Elrom
fonte
1

setDate () tem problemas com os limites do mês que são anotados nos comentários acima. Uma solução alternativa é encontrar a diferença de data usando carimbos de data / hora da época em vez dos métodos (surpreendentemente contra-intuitivos) no objeto Date. Ou seja,

function getPreviousMonday(fromDate) {
    var dayMillisecs = 24 * 60 * 60 * 1000;

    // Get Date object truncated to date.
    var d = new Date(new Date(fromDate || Date()).toISOString().slice(0, 10));

    // If today is Sunday (day 0) subtract an extra 7 days.
    var dayDiff = d.getDay() === 0 ? 7 : 0;

    // Get date diff in millisecs to avoid setDate() bugs with month boundaries.
    var mondayMillisecs = d.getTime() - (d.getDay() + dayDiff) * dayMillisecs;

    // Return date as YYYY-MM-DD string.
    return new Date(mondayMillisecs).toISOString().slice(0, 10);
}
jtschoonhoven
fonte
1

Aqui está a minha solução:

function getWeekDates(){
    var day_milliseconds = 24*60*60*1000;
    var dates = [];
    var current_date = new Date();
    var monday = new Date(current_date.getTime()-(current_date.getDay()-1)*day_milliseconds);
    var sunday = new Date(monday.getTime()+6*day_milliseconds);
    dates.push(monday);
    for(var i = 1; i < 6; i++){
        dates.push(new Date(monday.getTime()+i*day_milliseconds));
    }
    dates.push(sunday);
    return dates;
}

Agora você pode escolher a data pelo índice de matriz retornado.

Krystian Wieczorek
fonte
0

Um exemplo do cálculo apenas matematicamente, sem nenhuma Datefunção.

const date = new Date();
const ts = +date;

const mondayTS = ts - ts % (60 * 60 * 24 * (7-4) * 1000);

const monday = new Date(mondayTS);
console.log(monday.toISOString(), 'Day:', monday.getDay());

const formatTS = v => new Date(v).toISOString();
const adjust = (v, d = 1) => v - v % (d * 1000);

const d = new Date('2020-04-22T21:48:17.468Z');
const ts = +d; // 1587592097468

const test = v => console.log(formatTS(adjust(ts, v)));

test();                     // 2020-04-22T21:48:17.000Z
test(60);                   // 2020-04-22T21:48:00.000Z
test(60 * 60);              // 2020-04-22T21:00:00.000Z
test(60 * 60 * 24);         // 2020-04-22T00:00:00.000Z
test(60 * 60 * 24 * (7-4)); // 2020-04-20T00:00:00.000Z, monday

// So, what does `(7-4)` mean?
// 7 - days number in the week
// 4 - shifting for the weekday number of the first second of the 1970 year, the first time stamp second.
//     new Date(0)          ---> 1970-01-01T00:00:00.000Z
//     new Date(0).getDay() ---> 4

Anton Korneychuk
fonte
0

uma versão mais generalizada disso ... isso lhe dará qualquer dia da semana atual, com base no dia que você especificar.

//returns the relative day in the week 0 = Sunday, 1 = Monday ... 6 = Saturday
function getRelativeDayInWeek(d,dy) {
  d = new Date(d);
  var day = d.getDay(),
      diff = d.getDate() - day + (day == 0 ? -6:dy); // adjust when day is sunday
  return new Date(d.setDate(diff));
}

var monday = getRelativeDayInWeek(new Date(),1);
var friday = getRelativeDayInWeek(new Date(),5);

console.log(monday);
console.log(friday);

Andy
fonte
-1

Confira: moment.js

Exemplo:

moment().day(-7); // last Sunday (0 - 7)
moment().day(7); // next Sunday (0 + 7)
moment().day(10); // next Wednesday (3 + 7)
moment().day(24); // 3 Wednesdays from now (3 + 7 + 7 + 7)

Bônus: também funciona com o node.js

pixelfreak
fonte
18
Essa não é uma resposta para a pergunta do OP. Ele tem uma data, digamos 08/07/14 (d / m / a). Ele quer obter o primeiro dia da semana (para o meu local esta seria a segunda-feira que acaba de passar, ou ontem) uma resposta à sua pergunta com momento seriamoment().startOf('week')
Jeroen Pelgrims
Observe que moment().startOf("week")pode dar a data do domingo anterior, dependendo das configurações de localidade. Nesse caso, use moment().startOf('isoWeek'): runkit.com/embed/wdpi4bjwh6rt
Harm te Molder
PS Docs em startOf(): momentjs.com/docs/#/manipulating/start-of
Harm te Molder