Trova la data più vicina, data la data target e il giorno della settimana


12

Trova la data più vicina a una data target per un determinato giorno della settimana.

Ad esempio, data una data 20161219e un giorno della settimana di Friday (6), la risposta è 20161216.

Un altro esempio, data la data 20161219e il giorno della settimana di Wednesday (4), è la risposta 20161221.

Un ultimo esempio, data la data 20161219e il giorno della settimana di Monday (2), è la risposta 20161219.

Regole:

  • Il formato della data per l'input e l'output deve corrispondere. Negli esempi, ho usato yyyymmdd, ma è possibile utilizzare qualsiasi formato purché l'anno (almeno due cifre), il mese e il giorno del mese siano "leggibili dall'uomo".
  • Il giorno della settimana viene inserito come numero intero. Nel mio esempio, la domenica è il primo giorno della settimana, quindi è il numero del giorno della settimana 1. Puoi avere qualsiasi numerazione per il giorno della settimana, purché la noti quando differisce dall'esempio.
  • Gli anni dal 1970 al 2030 devono essere sistemati.
  • Sono consentiti strumenti e librerie per la data in linguaggio comune, ma viene dato credito stradale a coloro che scelgono di non usarli.
  • Vince il numero minimo di byte .

2
Le risposte potrebbero prendere la data in una forma diversa se conveniente? Anche i giorni della settimana sono stati scomodi per le lingue che considerano il lunedì il primo giorno della settimana
Blue

4
Sì, i severi requisiti di formato rendono questa attività più sull'analisi / conversione / formattazione, piuttosto che sulla ricerca della data effettiva. Sarebbe stato meglio che IMO lo specificasse in base a " Puoi accettare la data e il giorno della settimana in qualsiasi formato ragionevole, purché usi lo stesso formato per input e output ". Ma dal momento che un gruppo di persone ha già inviato risposte, suppongo che debba essere conservato come è ora.
smls

@smls Sono d'accordo. Lezione imparata per la prossima volta.
Brett Vander,

1
@BrettVanderVeen Non penso che sia troppo tardi per allentare i requisiti. Puoi semplicemente aggiungere un commento a ciascuna delle (attualmente 8) risposte sulle specifiche aggiornate. L'ho fatto in occasione.
Adám,

Risposte:


1

Perl 6 , 46 byte

{~first *.day-of-week==$^b,Date.new($^a)-3..*}

Una lambda che accetta due argomenti: una stringa di data in yyyy-mm-ddformato e un numero di giorno della settimana compreso tra 1= lunedì e 7= domenica.

Spiegazione:

                           Date.new($^a)       # Construct Date object from first argument.
                                        -3     # Subtract 3 days.
                                          ..*  # Construct a Range from that, to infinity.
  first                   ,                    # Iterate the range, and return first date...
        *.day-of-week==$^b                     # whose weekday number equals the second arg.

Utilizzando il formato della data e del giorno della settimana usato negli esempi, sarebbe 88 byte:

{S:g/\-//with ~first *.day-of-week==($^b-2)%7+1,Date.new(|($^a~~/(....)(..)(..)/))-3..*}

Cordiali saluti, ho semplificato le regole di formato data e giorno della settimana. Sentiti libero di inviare nuovamente.
Brett Vander, dal

@BrettVanderVeen: aggiornato.
smls

2

Perl 6 , 83 byte

->$_,\w{~(Date.new(|m/(....)(..)(..)/)-3...*.day-of-week%7+1==w)[*-1]~~{S:g/"-"//}}

Provalo

allargato

->     # pointy block lambda
  $_,
  \w
{
  ~(  # turn into a Str

    Date.new( |m/(....)(..)(..)/ ) - 3 # three days earlier
    ...                                # generate a sequence
    *.day-of-week % 7 + 1 == w         # stop when the right day is found

  )[*-1]  # the last one

  ~~      # apply the following block

  {
    S:g/"-"//  # remove 「-」
  }
}

Cordiali saluti, ho semplificato le regole di formato data e giorno della settimana. Sentiti libero di inviare nuovamente.
Brett Vander, dal

2

JavaScript (ES6), 93 byte

(s,n,d=new Date(s))=>d.setDate(d.getDate()+(n+9-d.getDay())%7-3)&&d.toISOString().slice(0,10)

Utilizza il %Y-%m-%dformato data. Se %a %b %d %Yè un formato data accettabile, quindi per 82 byte:

(s,n,d=new Date(s))=>d.setDate(d.getDate()+(n+9-d.getDay())%7-3)&&d.toDateString()

Potrei salvare altri 2 byte richiedendo domenica = 10 a sabato = 16, ma è una sciocca mappatura del giorno della settimana. Versione precedente di 142 141 byte (grazie a @Guedes) che utilizzava il formato data AAAAMMGG specifico, con la sua spiegazione:

(s,n,d=new Date(s.replace(/(?=..(..)?$)/g,'-')))=>d.setDate(d.getDate()+(n+9-d.getDay())%7-3)&&d.toISOString().replace(/-(..)-(..).*/,'$1$2')

Sembra troppo lungo. Spiegazione: Innanzitutto, inserisce -s nella data per ottenerla in formato ISO che new Datepuò quindi analizzare. Quindi, confronta il giorno desiderato con il giorno effettivo per ottenere un valore compreso tra -3e 3per l'offset effettivo. La magia 9deriva da 7(perché %è modulo CPU, non vero modulo) più 3(per l' -3offset) meno 1(perché nè 1-indicizzato e getDay0-indicizzato). La data viene quindi riconvertita in formato ISO e i caratteri indesiderati vengono rimossi.


Puoi salvare un byte cambiando il primo rimpiazzo in.replace(/(?=..(..)?$)/g,'-')
Washington Guedes il

Cordiali saluti, ho semplificato le regole di formato data e giorno della settimana. Sentiti libero di inviare nuovamente.
Brett Vander, dal

1

Python, 150 149 byte

from datetime import*
lambda s,n,t='%Y%m%d':[d for d in[datetime.strptime(s,t)+timedelta(o-3)for o in range(7)]if(n-2)%7==d.weekday()][0].strftime(t)

Oouuf, 149. repl.it

Funzione senza nome che prende una stringa s, la data come specificato (stringa di formato usando t='%Y%m%d'sia per l'input e l'output) e un numero in [1,7], n.
Ispeziona i sette giorni a partire da tre giorni prima di tre giorni dopo quello indicato per il giorno della settimana richiesto.
La settimana datetimeinizia lunedì e si basa su zero, quindi il test è (n-2)%7==d.weekday().


Cordiali saluti, ho semplificato le regole di formato data e giorno della settimana. Sentiti libero di inviare nuovamente.
Brett Vander, dal

1

Bash + coreutils, 50

date -d$1+$[($2-`date -d$1 +%u`+9)%7-3]day +%Y%m%d

Provalo online .

  • date -d$1 +%uindica il giorno della settimana (1..7); 1 è lunedì
  • Questo viene sottratto dal giorno di input della settimana per fornire una differenza di indici del giorno. Vogliamo aggiungere un fattore compreso nell'intervallo [-3, 3] alla data di input per ottenere la data più vicina, quindi aggiungiamo un fattore magico 9, prendiamo il modulo 7, quindi sottraggiamo 3. Il fattore magico 9 è 3 + 7 - 1. Il 3 regola l'intervallo di input per l'intervallo [-3, 3] e viene nuovamente sottratto dopo il modulo. Il 7 è necessario perché bash modulo è uguale al modulo CPU e può dare risultati -ve - aggiungendo 7 aggiustamenti nel giusto intervallo. -1 è perché nell'input, 1 è domenica, ma con l'output% u, 1 è lunedì.
  • L'esterno datequindi analizza <input date> + <magic factor>dayse lo presenta nel formato AAAAMMGG.

Cordiali saluti, ho semplificato le regole di formato data e giorno della settimana. Sentiti libero di inviare nuovamente.
Brett Vander, dal

1

Linguaggio macro SAS, 110 byte

%macro s(d,a);%put %sysfunc(putn(%sysfunc(intnx(week.&a.,%eval(%sysfunc(putn(&d,8.))-4),1)),yymmddn8.));%mend;

Un linguaggio da golf terribile ma ecco la spiegazione (dall'interno verso l'esterno):

Creare una macro sche accetta un input data de un giorno della settimana numerico a. Quindi %eval(%sysfunc(putn(&d,8.))-4)converte la data in una data numerica SAS e la diminuisce di 4 giorni. La intnxfunzione restituisce quindi la ricorrenza successiva del giorno della settimana specificato. putnquindi formatta la data su yyyymmdd e %putstampa l'output sul registro.


Cordiali saluti, ho semplificato le regole di formato data e giorno della settimana. Sentiti libero di inviare nuovamente.
Brett Vander, dal

1

Mathematica, 85 49 byte

#~DatePlus~Mod[#2-#~DateValue~"ISOWeekDay",7,-3]&

Il formato di input per le date è un elenco {2016, 12, 16}o un effettivo DateObject(penso che anche alcuni altri funzionino, ma li ho testati). In entrambi i casi, il formato di output corrisponderà automaticamente. La numerazione dei giorni inizia 1il lunedì.

L'idea è di calcolare la differenza tra il giorno della settimana di input e il giorno della settimana di destinazione con #2-#~DateValue~"ISOWeekDay"e quindi [-3, 3]mapparlo utilizzando un modulo con offset (cioè Mod[...,7,-3]). Il risultato viene semplicemente aggiunto alla data di input (l'unità predefinita per l'aggiunta dell'oggetto data è giorni).


Cordiali saluti, ho semplificato le regole di formato data e giorno della settimana. Sentiti libero di inviare nuovamente.
Brett Vander, dal

@BrettVanderVeen grazie, modificato.
Martin Ender,

1

R, 119 77 56 byte

Funzione senza nome che accetta due input, la data D(stringa) e il giorno d(numerico).

function(D,d,s=-3:3+as.Date(D))s[lubridate::wday(s)==d]

Utilizza la funzione wday()dal lubridatepacchetto. Può convertire comodamente gli Dateoggetti in giorni della settimana con il 1trattamento predefinito di domenica.

Modifica: I / O è ora il valore predefinito della as.Date()funzione:"YYYY-mm-dd"

Ungolfed e spiegato

function(D,d){
    D=as.Date(D);            # Format input date
    s=-3:3+D;                # Generate sequence of +- 3 days
    s[lubridate::wday(s)==d] # Match the weekday that equals to target day                                    
}

Modifica: ora crea una sequenza di +-3giorni per i quali è possibile trovare un determinato giorno della settimana. Successivamente dobbiamo abbinare solo un giorno che ha reso il problema molto più semplice.


Cordiali saluti, ho semplificato le regole di formato data e giorno della settimana. Sentiti libero di inviare nuovamente.
Brett Vander, dal

@BrettVanderVeen Grazie, aggiornato.
Billywob,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.