ISO 8601 Tarihlerini Doğrularken Saf Düzenli İfadeleri Yendi


12

In RX ile doğrula ISO 8601 , meydan için yalnızca standart normal ifadeler kullanmak oldu standart tarih biçimleri doğrulamak ve değerler (eski RX için ortak bir iştir, ikincisi sıradışı oldu). Kazanan cevapta 778 bayt kullanıldı. Bu zorluk, seçtiğiniz herhangi bir dili kullanarak, ancak özel tarih işlevleri veya sınıflar olmadan bunu yenmektir .

Meydan okuma

En kısa kodu bulun

  1. Proleptik Gregoryen takvimindeki olası her tarihi (1582'de ilk kabulünden önceki tüm tarihler için de geçerlidir) doğrular ,
  2. geçersiz tarihle eşleşmiyor ve
  3. tarihleri ​​(ve saatleri) işlemek için önceden tanımlanmış herhangi bir işlev, yöntem, sınıf, modül veya benzeri kullanmaz, yani dize ve sayısal işlemlere dayanır.

Çıktı

Çıktı doğruluk veya falseydir. Tarihi çıktılamak veya dönüştürmek gerekli değildir.

Giriş

Giriş, 3 genişletilmiş ISO 8601 tarih biçiminden herhangi birinde tek bir dizedir - zaman yok.

İlk ikisi ±YYYY-MM-DD(yıl, ay, gün) ve ±YYYY-DDD(yıl, gün). Her ikisinin artık gün için özel kasaya ihtiyacı var. Bu genişletilmiş RX'ler tarafından ayrı ayrı eşleştirilirler:

(?<year>[+-]?\d{4,})-(?<month>\d\d)-(?<day>\d\d)
(?<year>[+-]?\d{4,})-(?<doy>\d{3})

Üçüncü girdi biçimi ±YYYY-wWW-D(yıl, hafta, gün) şeklindedir. Karmaşık sıçrama haftası paterni nedeniyle karmaşık olanıdır.

(?<year>[+-]?\d{4,})-W(?<week>\d\d)-(?<dow>\d)

Koşullar

Proleptik Gregoryen takvimindeki bir sıçrama yılı artık günü içerir …-02-29ve bu nedenle 366 gün uzunluğundadır …-366. Bu, (muhtemelen negatif) sıra sayısı 4 ile bölünebilir, ancak 400 ile bölünemezse 100 ile değil herhangi bir yılda olur. Bu takvimde sıfır yılı var ve artık bir yıl.

Bir uzun yıl ISO hafta takvimde bir 53 hafta içeriyor …-W53-…biri “diyebileceğimiz, sıçrama hafta ”. Bu, 1 Ocak'ın Perşembe olduğu tüm yıllarda ve ek olarak Çarşamba olduğu tüm artık yıllarda olur. 0001-01-01ve 2001-01-01Pazartesi. Genellikle 5 veya 6 yılda bir, görünüşte düzensiz bir düzende ortaya çıkıyor.

Bir yılda en az 4 basamak vardır. 10 basamaktan fazla yılların desteklenmesi gerekmez, çünkü bu evrenin yaşına yeterince yakındır (yaklaşık 14 milyar yıl). Öncü artı işareti isteğe bağlıdır, ancak gerçek standart 4 basamaktan fazla yıllar için gerekli olduğunu göstermektedir.

Kısmi veya kesilmiş tarihler, yani gün hassasiyetinden daha az olan tarihler kabul edilmemelidir. -Her durumda ayırma tireleri gerekir. (Bu ön koşullar, yönlendirmenin +her zaman isteğe bağlı olmasını mümkün kılar .)

kurallar

Bu kod golfü. Bayt cinsinden en kısa kod kazanır. Daha önceki cevap bir kravat kazanır.

Test senaryoları

Geçerli testler

2015-08-10
2015-10-08
12015-08-10
-2015-08-10
+2015-08-10
0015-08-10
1582-10-10
2015-02-28
2016-02-29
2000-02-29
0000-02-29
-2000-02-29
-2016-02-29
+2016-02-29
200000-02-29
-200000-02-29
+200000-02-29
2016-366
2000-366
0000-366
-2000-366
-2016-366
+2016-366
2015-081
2015-W33-1
2015-W53-7
+2015-W53-7
+2015-W33-1
-2015-W33-1
 2015-08-10 

Sonuncusu isteğe bağlı olarak geçerlidir, yani giriş dizelerindeki ön ve arka boşluklar kesilebilir.

Geçersiz biçimler

-0000-08-10     # that's an arbitrary decision
15-08-10        # year is at least 4 digits long
2015-8-10       # month (and day) is exactly two digits long, i.e. leading zero is required
015-08-10       # year is at least 4 digits long
20150810        # though a valid ISO format, we require separators; could also be interpreted as a 8-digit year
2015 08 10      # separator must be hyphen-minus
2015.08.10      # separator must be hyphen-minus
2015–08–10      # separator must be hyphen-minus
2015-0810
201508-10       # could be October in the year 201508
2015 - 08 - 10  # no internal spaces allowed
2015-w33-1      # letter ‘W’ must be uppercase
2015W33-1       # it would be unambiguous to omit the separator in front of a letter, but not in the standard
2015W331        # though a valid ISO format we require separators
2015-W331
2015-W33        # a valid ISO date, but we require day-precision
2015W33         # though a valid ISO format we require separators and day-precision
2015-08         # a valid ISO format, but we require day-precision
201508          # a valid but ambiguous ISO format
2015            # a valid ISO format, but we require day-precision

Geçersiz tarihler

2015-00-10  # month range is 1–12
2015-13-10  # month range is 1–12
2015-08-00  # day range is 1–28 through 31
2015-08-32  # max. day range is 1–31
2015-04-31  # day range for April is 1–30
2015-02-30  # day range for February is 1–28 or 29
2015-02-29  # day range for common February is 1–28
2100-02-29  # most century years are non-leap
-2100-02-29 # most century years are non-leap
2015-000    # day range is 1–365 or 366
2015-366    # day range is 1–365 in common years
2016-367    # day range is 1–366 in leap years
2100-366    # most century years are non-leap
-2100-366   # most century years are non-leap
2015-W00-1  # week range is 1–52 or 53
2015-W54-1  # week range is 1–53 in long years
2016-W53-1  # week range is 1–52 in short years
2015-W33-0  # day range is 1–7
2015-W33-8  # day range is 1–7

2
konu dışı, ancak belki yararlı - Yığın Taşması: stackoverflow.com/questions/28020805/… (eğer göndermemem gerekiyorsa, söyle bana)
Daniele D

Programcı bir YEC (Young-Earth Creationist) ise ne olur?
Sızan Rahibe

Tam -0000-08-10olarak keyfi karar nedir? Yıla negatif 0 olarak izin vermiyor musunuz?
edc65

@ edc65 Evet, +0000-08-10ve 0000-08-10bunun yerine kullanılmalıdır. Not olsa da, bu meydan okuma düzenli ifade varyantında kabul cevap (yani bir nedenle başarısız koşulu gerçekten değil, bu özel test durumu başarısız olduğunu gerektiği değil, bir zorunluluk ).
Crissov

@KennyLau O zaman programcı yanlış .
Arcturus

Yanıtlar:


2

JavaScript (ES6), 236

Negatif 0 yıla izin veren 236 bayt ( -0000). Doğru veya yanlış döndürür

s=>!!([,y,w,d]=s.match(/^([+-]?\d{4,})(-W?\d\d)?(-\d{1,3})$/)||[],n=y%100==0&y%400!=0|y%4!=0,l=((l=y-1)+8-~(l/4)+~(l/100)-~(l/400))%7,l=l==5|l==4&!n,+d&&(-w?d>`0${2+n}0101001010`[~w]-32:w?(w=w.slice(2),w>0&w<(53+l)&d>-8):d[3]&&d>n-367))

Negatif 0 kesme 2 bayt için kontrol ekleme ancak 13 ekler. Javascript sayısal sayı -0var olduğunu ve özel 0, eşit olmak üzere kasalı 1/-0olduğunu unutmayın -Infinity. Bu sürüm 0 veya 1 döndürür

s=>([,y,w,d]=s.match(/^([+-]?\d{4,})(-W?\d\d)?(-\d{1,3})$/)||[],n=y%100==0&y%400!=0|y%4!=0,l=((l=y-1)+8-~(l/4)+~(l/100)-~(l/400))%7,l=l==5|l==4&!n,+d&&(-w?d>`0${2+n}0101001010`[~w]-32:w?(w=w.slice(2),w>0&w<(53+l)&d>-8):d[3]&&d>n-367))&!(!+y&1/y<0)

Ölçek

Check=
  s=>!! // to obtain a true/false 
  (
    // parse year in y, middle part in w, day in d
    // day will be negative with 1 or 3 numeric digits and could be 0
    // week will be '-W' + 2 digits
    // month will be negative with2 digits and could be 0
    // if the date is in format yyyy-ddd, then w is empty
    [,y,w,d] = s.match(/^([+-]?\d{4,})(-W?\d\d)?(-\d{1,3})$/) || [],
    n = y%100==0 & y%400!=0 | y%4!=0, // n: not leap year
    l = ((l=y-1) + 8 -~(l/4) +~(l/100) -~(l/400)) % 7, 
    l = l==5| l==4 & !n, // l: long year (see http://mathforum.org/library/drmath/view/55837.html)
    +d && ( // if d is not empty and not 0
     -w // if w is numeric and not 0, then it's the month (negative)
     ? d > `0${2+n}0101001010`[~w] - 32 // check month length (for leap year too)
      : w // if w is not empty, then it's the week ('-Wnn')
        ? ( w = w.slice(2), w > 0 & w < (53+l) & d >- 8) // check long year too
        : d[3] && d > n-367 // else d is the prog day, has to be 3 digits and < 367 o 366
    )
  )

console.log=x=>O.textContent += x +'\n'

OK=['1900-01-01','2015-08-10','2015-10-08','12015-08-10','-2015-08-10','+2015-08-10'
,'0015-08-10','1582-10-10','2015-02-28','2016-02-29','2000-02-29'
,'0000-02-29','-2000-02-29','-2016-02-29','+2016-02-29','200000-02-29'
,'-200000-02-29','+200000-02-29','2016-366','2000-366','0000-366'
,'-2000-366','-2016-366','+2016-366','2015-081','2015-W33-1'
,'2015-W53-7','+2015-W53-7','+2015-W33-1','-2015-W33-1','2015-08-10']

KO=['-0000-08-10','15-08-10','2015-8-10','015-08-10','20150810','2015 08 10'
,'2015.08.10','2015–08–10','2015-0810','201508-10','2015 - 08 - 10','2015-w33-1'
,'2015W33-1','2015W331','2015-W331','2015-W33','2015W33','2015-08','201508'
,'2015','2015-00-10','2015-13-10','2015-08-00','2015-08-32','2015-04-31'
,'2015-02-30','2015-02-29','2100-02-29','-2100-02-29','2015-000'
,'2015-366','2016-367','2100-366','-2100-366','2015-W00-1'
,'2015-W54-1','2016-W53-1','2015-W33-0','2015-W33-8']

console.log('Valid')
OK.forEach(x=>console.log(Check(x)+' '+x))
console.log('Not valid')
KO.forEach(x=>console.log(Check(x)+' '+x))
<pre id=O></pre>

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.