TargetDateと曜日を指定して、最も近い日付を見つけます


12

特定の曜日のTargetDateに最も近い日付を見つけます。

たとえば、の日付20161219と曜日を指定するFriday (6)と、答えはになり20161216ます。

別の例では、日付20161219と曜日を指定するWednesday (4)と、答えはになり20161221ます。

最後の例では、日付20161219と曜日を指定するMonday (2)と、答えはになり20161219ます。

ルール:

  • 入力と出力の日付形式は一致する必要があります。例ではを使用yyyymmddしましたが、年(少なくとも2桁)、月、および日が「人間が読める」形式である限り、任意の形式を使用できます。
  • 曜日は整数として入力されます。私の例では、日曜日が週の最初の日であるため、曜日番号1です。例と異なる場合は、曜日番号をメモしておけば、曜日番号を付けることができます。
  • 1970年から2030年まで対応する必要があります。
  • 共通言語の日付ツールとライブラリは許可されていますが、それらを使用しないことを選択した人には、ストリートの信用が与えられています。
  • 最小バイト数が優先されます

2
回答が便利な場合、別の形式で日付を取ることができますか?また、曜日は月曜日を週の最初の日とする言語にとっては不便です
Blue

4
確かに、厳密な形式の要件により、このタスクは実際の日付の検出よりも、解析/変換/フォーマットに関するものです。IMOは、「入力と出力に同じ形式を使用する限り、任意の妥当な形式で日付と曜日を受け入れることができます。」の行に沿って指定する方が良いでしょう。しかし、多くの人々がすでに回答を提出しているので、私はそれを今のままにしておく必要があると思います。
smls 16

@smls同意します。次回のために学んだ教訓。
ブレットヴァンダーヴィーン16

1
@BrettVanderVeen要件を緩和するのに遅すぎるとは思わない。更新された仕様に関する(現在8つの)回答のそれぞれにコメントを追加できます。私は時々そのようなことをしました。
アダム16

回答:


1

Perl 6、46バイト

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

2つの引数を受け取るラムダ:yyyy-mm-dd形式の日付文字列、および1= Mondayと7= Sundayの間の曜日番号。

説明:

                           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.

例で使用されている日付と曜日の形式を使用すると、88バイトになります。

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

参考までに、日付と曜日の形式ルールを緩和しました。再送信してください。
ブレットヴァンダーヴィーン16

@BrettVanderVeen:更新されました。
smls 16

2

Perl 6、83バイト

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

それを試してみてください

拡大

->     # 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 「-」
  }
}

参考までに、日付と曜日の形式ルールを緩和しました。再送信してください。
ブレットヴァンダーヴィーン16

2

JavaScript(ES6)、93バイト

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

%Y-%m-%d日付形式を使用します。場合は%a %b %d %Y82バイト、次いで、許容される日付の形式です。

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

日曜日= 10から土曜日= 16を要求することでさらに2バイト節約できますが、これは馬鹿げた曜日のマッピングです。特定のYYYYMMDD日付形式を使用した以前の142 141バイト(@Guedesのおかげ)バージョンとその説明:

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

これは長すぎます。説明:最初に、-sを日付に挿入して、ISO形式に変換してnew Dateから解析します。その後、間の値を取得するために、実際の日で希望日を比較-3し、3実際のオフセットのために。魔法97%真のモジュロではなくCPUモジュロであるため)プラス3-3オフセットの場合)マイナス1n1インデックスでgetDay0 インデックスであるため)にます。その後、日付は再びISO形式に変換され、不要な文字が削除されます。


最初の置換を変更する1バイトを保存できます.replace(/(?=..(..)?$)/g,'-')
Washington Guedes

参考までに、日付と曜日の形式ルールを緩和しました。再送信してください。
ブレットヴァンダーヴィーン16

1

Python、 150 149バイト

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)

ウーフ、149。 149。repl.it

文字列s、指定された日付(t='%Y%m%d'入力と出力の両方に書式文字列を使用)、および[1,7]の数値を受け取る名前のない関数n
要求された曜日に指定された日付の3日前から3日後までの7日間を検査します。
の週はdatetime月曜日から始まり、ゼロに基づいているため、テストは(n-2)%7==d.weekday()です。


参考までに、日付と曜日の形式ルールを緩和しました。再送信してください。
ブレットヴァンダーヴィーン16

1

Bash + coreutils、50

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

オンラインでお試しください

  • date -d$1 +%u曜日(1..7)を提供します。1は月曜日です
  • これは、曜日の入力インデックスから差を付けるために、入力された曜日から差し引かれます。[-3、3]の範囲内の係数を入力日付に追加して最も近い日付を取得するため、マジックファクター9を追加し、モジュロ7を取り、3を減算します。マジックファクター9は3 + 7 - 1です。3は、範囲[-3、3]の入力範囲を調整し、モジュロ後に再び減算されます。bashモジュロはCPUモジュロと同じであり、-veの結果が得られるため、7が必要です。7を追加すると適切な範囲に調整されます。-1は、入力では1は日曜日ですが、%u出力では1は月曜日であるためです。
  • 外側はdateそれを解析<input date> + <magic factor>daysし、YYYYMMDD形式で表示します。

参考までに、日付と曜日の形式ルールを緩和しました。再送信してください。
ブレットヴァンダーヴィーン16

1

SASマクロ言語、110バイト

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

ひどいゴルフ言語ですが、ここに説明があります(内側から):

s日付の入力dと数値の曜日を受け入れるマクロを作成しますa。次に%eval(%sysfunc(putn(&d,8.))-4)、日付をSAS数値日付に変換し、4日間減らします。intnx関数は、指定された曜日の次の出現を返します。putn次に、日付をyyyymmddにフォーマットし直して%put、出力をログに出力します。


参考までに、日付と曜日の形式ルールを緩和しました。再送信してください。
ブレットヴァンダーヴィーン16

1

Mathematica、85 49バイト

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

日付の入力形式は、リストのような形式{2016, 12, 16}または実際の形式のいずれかですDateObject(他のいくつかも同様に機能すると思いますが、これらをテストしました)。どちらの場合でも、出力形式は自動的に一致します。日の番号付けはから始まります1月曜日ます。

アイデアは、入力平日とターゲット平日との差を計算し、オフセット付きモジュロを使用#2-#~DateValue~"ISOWeekDay"してマッピングすることです[-3, 3](ie Mod[...,7,-3])。結果は入力日付に単純に追加されます(日付オブジェクトの追加のデフォルト単位は日です)。


参考までに、日付と曜日の形式ルールを緩和しました。再送信してください。
ブレットヴァンダーヴィーン16

@BrettVanderVeenありがとう、編集。
マーティンエンダー

1

R、119 77 56バイト

日付D(文字列)と日d(数値)の2つの入力を取る名前のない関数。

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

パッケージの関数wday()を使用しlubridateます。デフォルトで日曜日として扱われDate、オブジェクトを平日に便利に変換でき1ます。

編集:I / Oがas.Date()関数のデフォルトになりました:"YYYY-mm-dd"

非ゴルフと説明

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                                    
}

編集:+-3特定の平日が見つかることが保証される一連の日を作成します。その後、問題をより簡単にする1日のみを一致させる必要があります。


参考までに、日付と曜日の形式ルールを緩和しました。再送信してください。
ブレットヴァンダーヴィーン16

@BrettVanderVeenありがとう、更新しました。
ビリーウォブ16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.