TargetDate ve Haftanın Günü verildiğinde en yakın Tarihi bulun


12

Belirli bir Haftanın Günü için TargetDate'e en yakın Tarihi bulun.

Örneğin, bir tarih 20161219ve haftanın bir günü verildiğinde Friday (6), cevap verilir 20161216.

Başka bir örnek, verilen bir tarih 20161219ve haftanın bir günü Wednesday (4), cevaptır 20161221.

Son bir örnek, verilen bir tarih 20161219ve haftanın bir günü Monday (2), cevaptır 20161219.

Kurallar:

  • Giriş ve çıkışın Tarih biçimi eşleşmelidir. Örneklerde kullandım yyyymmdd, ancak yıl (en az iki basamaklı), ay ve ayın günü "insan tarafından okunabilir" olduğu sürece herhangi bir biçimi kullanabilirsiniz.
  • Haftanın Günü bir tamsayı olarak girilir. Örneğimde, Pazar haftanın ilk günü, dolayısıyla haftanın günü sayısı 1. Örnekten farklı olduğunda not ettiğiniz sürece herhangi bir Haftanın Günü numaralandırmasına sahip olabilirsiniz.
  • 1970 ile 2030 yılları arasında uyum sağlanmalıdır.
  • Ortak dil tarihi araçlarına ve kitaplıklarına izin verilir, ancak bunları kullanmamayı seçenlere sokak kredisi verilir.
  • En az bayt sayısı kazanır.

2
Yanıtlar uygunsa tarihi farklı bir biçimde alabilir mi? Ayrıca haftanın günleri, Pazartesi günü haftanın ilk günü olarak kabul edilen diller için de rahatsızlık verdi
Blue

4
Evet, katı biçim gereksinimleri bu görevi gerçek tarih bulmadan çok ayrıştırma / dönüştürme / biçimlendirme hakkında yapar. IMO, " Giriş ve çıkış için aynı biçimi kullandığınız sürece, tarihi ve haftanın gününü makul bir biçimde kabul edebilirsiniz " satırında belirtmek daha iyi olurdu . Ancak bir grup insan zaten cevap gönderdiğinden, sanırım şu anda olduğu gibi tutması gerekiyor.
smls

@smls katılıyorum. Ders bir dahaki sefere öğrendi.
Brett VanderVeen

1
@BrettVanderVeen Gereksinimleri gevşetmek için çok geç olduğunu sanmıyorum. Güncellenmiş spesifikasyon hakkındaki her (şu anda 8) cevap için bir yorum ekleyebilirsiniz. Ben de öyle yaptım.
Adam

Yanıtlar:


1

Perl 6 , 46 bayt

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

İki bağımsız değişkeni kabul eden bir lambda: Biçimde bir tarih dizesi yyyy-mm-ddve 1= Pazartesi ile 7= Pazar arasında bir hafta içi sayı .

Açıklama:

                           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.

Örneklerde kullanılan tarih ve hafta içi biçimi kullanıldığında, 88 bayt olur:

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

Bilginize, tarih ve haftanın günü biçim kurallarını hafiflettim. Tekrar göndermek için çekinmeyin.
Brett VanderVeen

@BrettVanderVeen: Güncellendi.
smls

2

Perl 6 , 83 bayt

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

Dene

Expanded

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

Bilginize, tarih ve haftanın günü biçim kurallarını hafiflettim. Tekrar göndermek için çekinmeyin.
Brett VanderVeen

2

JavaScript (ES6), 93 bayt

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

%Y-%m-%dTarih biçimini kullanır . Kabul %a %b %d %Yedilebilir bir tarih biçimiyse, 82 bayt için:

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

Pazar = 10'dan Cumartesi = 16'ya kadar 2 bayt daha kaydedebilirim, ancak bu haftanın aptal bir gün eşlemesi. Önceki 142 141 bayt (@Guedes sayesinde), açıklamasıyla birlikte belirli YYYYMMDD tarih biçimini kullanan sürüm:

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

Bu çok uzun hissettiriyor. Açıklama: İlk olarak, daha sonra ayrıştırabilen -ISO biçimini almak için s tarihini ekler new Date. Ardından, gerçek ofset arasında -3ve değeri için bir değer elde etmek için istenen günü gerçek günle karşılaştırır 3. Sihirli 9gelir 7(nedeniyle %, CPU modülo değil, gerçek modülo olan) 3için ( -3eksi ofset) 1(nedeniyle n1-endeksli ve getDay0 endeksli). Tarih daha sonra ISO biçimine dönüştürülür ve istenmeyen karakterler kaldırılır.


İlk bayt değiştirerek bir bayt kaydedebilirsiniz.replace(/(?=..(..)?$)/g,'-')
Washington Guedes

Bilginize, tarih ve haftanın günü biçim kurallarını hafiflettim. Tekrar göndermek için çekinmeyin.
Brett VanderVeen

1

Piton, 150 149 bayt

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

Dizeyi alan adsız işlev, sbelirtildiği gibi tarih ( t='%Y%m%d'hem giriş hem de çıkış için biçim dizesini kullanarak ) ve [1,7] 'de bir sayı n.
İstenen haftanın günü için verilen tarihten üç gün öncesinden üç gün öncesine kadar olan yedi günü inceler.
Hafta datetimePazartesi günü başlar ve sıfır tabanlıdır, bu nedenle test yapılır (n-2)%7==d.weekday().


Bilginize, tarih ve haftanın günü biçim kurallarını hafiflettim. Tekrar göndermek için çekinmeyin.
Brett VanderVeen

1

Bash + coreutils, 50

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

Çevrimiçi deneyin .

  • date -d$1 +%uhaftanın gününü verir (1..7); 1 Pazartesi
  • Bu, gün endekslerinde bir fark vermek için haftanın giriş gününden çıkarılır. En yakın tarihi almak için giriş tarihine [-3, 3] aralığında bir faktör eklemek istiyoruz, bu yüzden sihirli bir faktör 9 ekliyoruz, modulo 7'yi alıyoruz, sonra 3 çıkarıyoruz. Sihirli faktör 9 3 + 7 - 1. 3, [-3, 3] aralığı için giriş aralığını ayarlar ve modülodan sonra tekrar çıkarılır. 7 gereklidir, çünkü bash modulo CPU modulo ile aynıdır ve -ve sonuçlar verebilir - doğru aralığa 7 ayar ekler. -1, girdide 1 Pazar olduğu için% u çıktısıyla 1 Pazartesi olur.
  • Dış kısım YYYYMMDD biçiminde dateayrıştırır <input date> + <magic factor>daysve sunar.

Bilginize, tarih ve haftanın günü biçim kurallarını hafiflettim. Tekrar göndermek için çekinmeyin.
Brett VanderVeen

1

SAS Makro Dili, 110 Bayt

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

Korkunç bir golf dili ama burada açıklama (içten dışa):

sTarih girişini dve hafta içi sayısal girişi kabul eden bir makro oluşturun a. Ardından %eval(%sysfunc(putn(&d,8.))-4)tarihi SAS sayısal tarihine dönüştürür ve 4 gün azaltır. intnxFonksiyonu daha sonra belirtilen iş günü sonraki oluşumunu döndürür. putnsonra tarihi yyyymmdd olarak biçimlendirir ve %putçıktıyı günlüğe yazdırır.


Bilginize, tarih ve haftanın günü biçim kurallarını hafiflettim. Tekrar göndermek için çekinmeyin.
Brett VanderVeen

1

Mathematica, 85 49 bayt

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

Tarihler için giriş biçimi ya gibi bir liste {2016, 12, 16}ya da gerçek DateObject(Bence birkaç kişi de işe yarıyor, ama bunları test ettim). Her iki durumda da, çıktı biçimi otomatik olarak eşleşecektir. Gün numaralandırma 1Pazartesi günleri başlar .

Buradaki fikir, hafta içi ve hafta içi hedef arasındaki farkı hesaplamak #2-#~DateValue~"ISOWeekDay"ve sonra bunu [-3, 3]ofset (yani Mod[...,7,-3]) ile bir modulo kullanarak eşlemektir . Sonuç yalnızca giriş tarihine eklenir (tarih nesnesi ekleme için varsayılan birim günlerdir).


Bilginize, tarih ve haftanın günü biçim kurallarını hafiflettim. Tekrar göndermek için çekinmeyin.
Brett VanderVeen

@BrettVanderVeen teşekkürler, düzenlendi.
Martin Ender

1

R, 119 77 56 bayt

Tarih D(dize) ve gün d(sayısal) olmak üzere iki giriş alan adsız işlev .

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

Fonksiyonunu kullanır wday()gelen lubridatepaketin. Varsayılan olarak Pazar olarak değerlendirilerek Datenesneleri hafta günlerine kolayca dönüştürebilir 1.

Düzenleme: G / Ç şimdi as.Date()işlevin varsayılanıdır :"YYYY-mm-dd"

Açıklanamayan ve Açıklanan

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                                    
}

Düzenleme: Şimdi, +-3belirli bir hafta içi gün içinde bulunacağı garanti edilen günler dizisi oluşturur . Daha sonra sadece sorunu daha kolay hale getiren sadece bir gün eşleşmek zorunda.


Bilginize, tarih ve haftanın günü biçim kurallarını hafiflettim. Tekrar göndermek için çekinmeyin.
Brett VanderVeen

@BrettVanderVeen Teşekkürler, güncellendi.
Billywob
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.