Finden Sie das nächstgelegene Datum unter Angabe eines Zieldatums und eines Wochentags

12

Finden Sie das nächste Datum zu einem Zieldatum für einen bestimmten Wochentag.

Wenn Sie beispielsweise ein Datum 20161219und einen Wochentag für angeben Friday (6), lautet die Antwort 20161216.

Bei einem anderen Beispiel lautet die Antwort , wenn ein Datum 20161219und ein Wochentag angegeben Wednesday (4)sind 20161221.

Ein letztes Beispiel mit einem Datum 20161219und einem Wochentag von Monday (2)lautet die Antwort 20161219.

Regeln:

  • Das Datumsformat für die Eingabe und Ausgabe muss übereinstimmen. In den Beispielen habe ich verwendet yyyymmdd, aber Sie können jedes Format verwenden , solange das Jahr (mindestens zwei Ziffern), der Monat und der Tag des Monats "vom Menschen lesbar" sind.
  • Wochentag wird als Ganzzahl eingegeben. In meinem Beispiel ist Sonntag der erste Tag der Woche, daher ist es der Wochentag Nummer 1. Sie können jeden Wochentag nummerieren, sofern Sie ihn notieren, wenn er vom Beispiel abweicht.
  • Die Jahre 1970 bis 2030 müssen berücksichtigt werden.
  • Gängige Datumstools und -bibliotheken für Sprachen sind zulässig, aber diejenigen, die sie nicht verwenden, erhalten eine Straßenberechtigung.
  • Die geringste Anzahl von Bytes gewinnt.
Brett VanderVeen
quelle
2
Könnten Antworten das Datum in einer anderen Form anzeigen, wenn dies zweckmäßig ist? Auch die Wochentage wurden als unpraktisch für Sprachen angesehen, bei denen der Montag der erste Wochentag ist
Blue
4
Ja, die strengen Formatanforderungen machen diese Aufgabe mehr zum Parsen / Konvertieren / Formatieren als zum tatsächlichen Ermitteln des Datums. Wäre es IMO besser gewesen, wenn Sie das Datum und den Wochentag in einem angemessenen Format angeben würden , sofern Sie dasselbe Format für die Ein- und Ausgabe verwenden . Aber da einige Leute bereits Antworten eingereicht haben, denke ich, muss es so bleiben, wie es jetzt ist.
smls
Ich stimme zu. Lektion gelernt für das nächste Mal.
Brett VanderVeen
1
@BrettVanderVeen Ich glaube nicht, dass es zu spät ist, die Anforderungen zu lockern. Sie können einfach einen Kommentar zu jeder der (derzeit 8) Antworten zur aktualisierten Spezifikation hinzufügen. Ich habe das gelegentlich gemacht.
Adám

Antworten:

1

Perl 6 , 46 Bytes

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

Ein Lambda, das zwei Argumente akzeptiert: Eine Datumszeichenfolge im yyyy-mm-ddFormat und eine Wochentagszahl zwischen 1= Montag und 7= Sonntag.

Erläuterung:

                           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.

Unter Verwendung des in den Beispielen verwendeten Datums- und Wochentagsformats wären es 88 Bytes:

{S:g/\-//with ~first *.day-of-week==($^b-2)%7+1,Date.new(|($^a~~/(....)(..)(..)/))-3..*}
smls
quelle
Zu Ihrer Information, ich habe die Formatregeln für Datum und Wochentag vereinfacht. Fühlen Sie sich frei, erneut einzureichen.
Brett VanderVeen
@BrettVanderVeen: Aktualisiert.
smls
2

Perl 6 , 83 Bytes

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

Versuch es

Erweitert

->     # 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 「-」
  }
}
Brad Gilbert b2gills
quelle
Zu Ihrer Information, ich habe die Formatregeln für Datum und Wochentag vereinfacht. Fühlen Sie sich frei, erneut einzureichen.
Brett VanderVeen
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)

Verwendet das %Y-%m-%dDatumsformat. Wenn %a %b %d %Yes sich um ein akzeptables Datumsformat handelt, gilt für 82 Bytes Folgendes:

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

Ich könnte weitere 2 Bytes einsparen, indem ich Sonntag = 10 bis Samstag = 16 benötige, aber das ist eine alberne Wochentagszuordnung. Vorherige 142 141-Byte-Version (dank @Guedes), die das spezifische Datumsformat JJJJMMTT verwendet hat, mit der folgenden Erklärung:

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

Das fühlt sich viel zu lang an. Erläuterung: Fügt zuerst -s in das Datum ein, um es in das ISO-Format zu bringen, das new Datedann analysiert werden kann. Dann wird der gewünschte Tag mit dem tatsächlichen Tag verglichen, um einen Wert zwischen -3und 3für den tatsächlichen Versatz zu erhalten. Die Magie 9kommt von 7(weil %ist CPU Modulo, nicht wahr Modulo) plus 3(für den -3Offset) minus 1(weil nist 1-indiziert und getDayist 0-indiziert). Das Datum wird dann wieder in das ISO-Format konvertiert und die unerwünschten Zeichen entfernt.

Neil
quelle
Sie können ein Byte speichern, indem Sie die erste Ersetzung in ".replace(/(?=..(..)?$)/g,'-')
Washington Guedes
Zu Ihrer Information, ich habe die Formatregeln für Datum und Wochentag vereinfacht. Fühlen Sie sich frei, erneut einzureichen.
Brett VanderVeen
1

Python, 150 bis 149 Bytes

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

Unbenannte Funktion, die eine Zeichenfolge s, das angegebene Datum (unter Verwendung einer Formatzeichenfolge t='%Y%m%d'sowohl für die Eingabe als auch für die Ausgabe) und eine Zahl in [1,7] annimmt n.
Überprüft die sieben Tage ab drei Tagen vor drei Tagen nach dem für den gewünschten Wochentag angegebenen.
Die Woche datetimebeginnt am Montag und basiert auf Null, der Test ist also (n-2)%7==d.weekday().

Jonathan Allan
quelle
Zu Ihrer Information, ich habe die Formatregeln für Datum und Wochentag vereinfacht. Fühlen Sie sich frei, erneut einzureichen.
Brett VanderVeen
1

Bash + Coreutils, 50

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

Probieren Sie es online aus .

  • date -d$1 +%ugibt den Wochentag an (1..7); 1 ist Montag
  • Dies wird vom eingegebenen Wochentag abgezogen, um eine Differenz der Tagesindizes zu erhalten. Wir wollen dem Eingabedatum einen Faktor zwischen [-3, 3] hinzufügen, um das nächstgelegene Datum zu erhalten, also addieren wir einen magischen Faktor 9, nehmen das Modulo 7 und subtrahieren dann 3. Der magische Faktor 9 ist3 + 7 - 1 . Die 3 stellt den Eingangsbereich für den Bereich [-3, 3] ein und wird nach dem Modulo erneut subtrahiert. Die 7 ist erforderlich, da das Bash-Modulo mit dem CPU-Modulo identisch ist und zu -ve-Ergebnissen führen kann. Durch Hinzufügen von 7 Anpassungen in den richtigen Bereich. Das -1 ist, weil in der Eingabe 1 Sonntag ist, aber mit der% u-Ausgabe ist 1 Montag.
  • Das äußere dateanalysiert <input date> + <magic factor>daysund präsentiert es dann im Format JJJJMMTT.
Digitales Trauma
quelle
Zu Ihrer Information, ich habe die Formatregeln für Datum und Wochentag vereinfacht. Fühlen Sie sich frei, erneut einzureichen.
Brett VanderVeen
1

SAS-Makrosprache, 110 Bytes

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

Eine schreckliche Golfsprache, aber hier ist die Erklärung (von innen nach außen):

Erstellen Sie ein Makro s, das eine Datumseingabe dund einen numerischen Wochentag akzeptiert a. Dann %eval(%sysfunc(putn(&d,8.))-4)wandelt das Datum auf ein numerisches Datum SAS und dekrementiert sie durch 4 Tage. Die intnxFunktion gibt dann das nächste Vorkommen des angegebenen Wochentags zurück. putnFormatiert dann das Datum zurück auf JJJJMTT und %putdruckt die Ausgabe in das Protokoll.

J_Lard
quelle
Zu Ihrer Information, ich habe die Formatregeln für Datum und Wochentag vereinfacht. Fühlen Sie sich frei, erneut einzureichen.
Brett VanderVeen
1

Mathematica, 85 49 Bytes

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

Das Eingabeformat für Datumsangaben ist entweder eine Liste {2016, 12, 16}oder eine tatsächliche DateObject(ich denke, einige andere funktionieren auch, aber ich habe diese getestet). In beiden Fällen wird das Ausgabeformat automatisch angepasst. Die Tagesnummerierung beginnt 1montags.

Die Idee besteht darin, die Differenz zwischen dem eingegebenen Wochentag und dem Ziel-Wochentag mit zu berechnen #2-#~DateValue~"ISOWeekDay"und dann [-3, 3]mit einem Modulo mit Offset (dh Mod[...,7,-3]) abzubilden . Das Ergebnis wird einfach zum Eingabedatum addiert (die Standardeinheit für das Hinzufügen von Datumsobjekten ist Tage).

Martin Ender
quelle
Zu Ihrer Information, ich habe die Formatregeln für Datum und Wochentag vereinfacht. Fühlen Sie sich frei, erneut einzureichen.
Brett VanderVeen
@BrettVanderVeen danke, bearbeitet.
Martin Ender
1

R, 119 77 56 Bytes

Unbenannte Funktion, die zwei Eingaben akzeptiert, das Datum D(Zeichenfolge) und den Tag d(numerisch).

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

Verwendet die Funktion wday()aus dem lubridatePaket. Es kann DateObjekte bequem in Wochentage konvertieren, wobei 1es standardmäßig als Sonntag behandelt wird.

Bearbeiten: E / A ist jetzt die Standardeinstellung der as.Date()Funktion:"YYYY-mm-dd"

Ungolfed und erklärt

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                                    
}

Bearbeiten: Erstellt jetzt eine Folge von +-3Tagen, für die ein bestimmter Wochentag garantiert gefunden wird. Anschließend müssen wir nur noch einen Tag abgleichen, was das Problem erheblich vereinfacht hat.

Billywob
quelle
Zu Ihrer Information, ich habe die Formatregeln für Datum und Wochentag vereinfacht. Fühlen Sie sich frei, erneut einzureichen.
Brett VanderVeen
@BrettVanderVeen Danke, aktualisiert.
Billywob