เอาชนะการแสดงออกปกติอย่างบริสุทธิ์ที่การตรวจสอบความถูกต้อง ISO 8601 วันที่


12

ในการตรวจสอบการรับรองมาตรฐาน ISO 8601 โดย RXความท้าทายคือการใช้เพียงการแสดงออกปกติมาตรฐานในการตรวจสอบรูปแบบวันที่มาตรฐานและค่า (อดีตเป็นงานทั่วไปสำหรับ RX หลังเป็นเรื่องผิดปกติ) คำตอบที่ชนะใช้ 778 ไบต์ ความท้าทายนี้คือการเอาชนะโดยใช้ภาษาที่คุณเลือก แต่ไม่มีฟังก์ชั่นวันที่หรือชั้นเรียนพิเศษ

ท้าทาย

ค้นหารหัสที่สั้นที่สุดที่

  1. ตรวจสอบทุกวันที่เป็นไปได้ในปฏิทินเกรกอเรียนProleptic (ซึ่งใช้กับทุกวันก่อนที่จะมีการนำไปใช้ครั้งแรกในปี 1582)
  2. ไม่ตรงกับวันที่ไม่ถูกต้องและ
  3. ไม่ใช้ฟังก์ชันวิธีการคลาสโมดูลหรือสิ่งที่คล้ายกันสำหรับการจัดการวันที่ (และเวลา) ที่กำหนดไว้ล่วงหน้าเช่นอาศัยการทำงานของสตริงและตัวเลข

เอาท์พุต

ผลผลิตเป็นจริงหรือเท็จ ไม่จำเป็นต้องเอาท์พุทหรือแปลงวันที่

อินพุต

อินพุตเป็นสตริงเดี่ยวในรูปแบบวันที่ISO 8601ที่ขยายเพิ่ม 3 รูปแบบ - ไม่มีเวลา

สองรายการแรกคือ±YYYY-MM-DD(ปีเดือนวัน) และ±YYYY-DDD(ปีวัน) ทั้งสองต้องการปลอกพิเศษสำหรับวันอธิกสุรทิน พวกมันถูกจับคู่อย่างไร้เดียงสาโดย RXs ที่ขยายเพิ่มเหล่านี้

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

รูปแบบอินพุตที่สามคือ±YYYY-wWW-D(ปี, สัปดาห์, วัน) มันเป็นสิ่งที่ซับซ้อนเพราะรูปแบบการกระโดดสัปดาห์ที่ซับซ้อน

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

เงื่อนไข

ปีอธิกสุรทินในปฏิทินเกรกอเรียนโกเรียนมีวันก้าวกระโดด …-02-29และทำให้มันเป็น 366 วันนานจึง…-366มีอยู่ สิ่งนี้เกิดขึ้นในปีใด ๆ ที่มีเลขลำดับ (อาจเป็นลบ) หารด้วย 4 แต่ไม่เท่ากับ 100 เว้นแต่จะหารด้วย 400 ด้วย ปีศูนย์มีอยู่ในปฏิทินนี้และเป็นปีอธิกสุรทิน

ปีในปฏิทินสัปดาห์ ISO มีสัปดาห์ที่ 53 …-W53-…ซึ่งใครสามารถคำ“ เผ่นสัปดาห์ ” สิ่งนี้เกิดขึ้นในทุก ๆ ปีที่ 1 มกราคมเป็นวันพฤหัสบดีและจะเพิ่มขึ้นทุกปี 0001-01-01และ2001-01-01เป็นวันจันทร์ ปรากฎว่าเกิดขึ้นทุก ๆ 5 หรือ 6 ปีตามปกติในรูปแบบที่ไม่ปกติ

ปีมีตัวเลขอย่างน้อย 4 หลัก ปีที่มีตัวเลขมากกว่า 10 หลักไม่จำเป็นต้องได้รับการสนับสนุนเพราะมันอยู่ใกล้กับยุคของจักรวาล (ประมาณ 14 พันล้านปี) เครื่องหมายบวกชั้นนำเป็นตัวเลือกถึงแม้ว่ามาตรฐานจริงแนะนำว่าควรใช้เวลาหลายปีด้วยตัวเลขมากกว่า 4 หลัก

ต้องไม่ยอมรับวันที่บางส่วนหรือที่ถูกตัดทอนเช่นที่น้อยกว่าความแม่นยำของวัน -จำเป็นต้องมีการคั่นด้วยยติภัง (ปัจจัยพื้นฐานเหล่านี้ทำให้เป็นไปได้ที่+จะเป็นทางเลือกเสมอ)

กฎระเบียบ

นี่คือรหัสกอล์ฟ รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ คำตอบก่อนหน้านี้ชนะเสมอกัน

กรณีทดสอบ

การทดสอบที่ถูกต้อง

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 

ส่วนสุดท้ายเป็นทางเลือกที่ถูกต้องเช่นช่องว่างนำหน้าและต่อท้ายในสตริงอินพุตอาจถูกตัดออก

รูปแบบไม่ถูกต้อง

-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

วันที่ไม่ถูกต้อง

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
ปิดหัวข้อ แต่อาจมีประโยชน์ - สแต็คโอเวอร์โฟลว์: stackoverflow.com/questions/28020805/ (ถ้าฉันไม่ควรโพสต์สิ่งนั้นบอกฉัน)
Daniele D

จะเป็นอย่างไรถ้าโปรแกรมเมอร์คือ YEC (Young-Earth Creationist)
แม่ชีที่รั่ว

เกี่ยวกับ-0000-08-10การตัดสินใจโดยพลการของอะไร ไม่อนุญาตให้ปีเป็นลบ 0 ใช่หรือไม่
edc65

@ edc65 ใช่+0000-08-10และ0000-08-10ควรใช้แทน อย่างไรก็ตามโปรดทราบว่าคำตอบที่ได้รับการยอมรับในชุดรูปแบบการแสดงออกปกติของความท้าทายนี้ล้มเหลวในกรณีทดสอบนี้โดยเฉพาะดังนั้นจึงไม่ใช่เงื่อนไขที่ล้มเหลวจริงๆ (เช่นควรไม่ควรต้อง )
Crissov

@KennyLau แล้วโปรแกรมเมอร์ที่ไม่ถูกต้อง
Arcturus

คำตอบ:


2

JavaScript (ES6), 236

236 ไบต์อนุญาตลบ 0 ปี ( -0000) ส่งคืนจริงหรือเท็จ

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))

เพิ่มการตรวจสอบเชิงลบ 0 ตัด 2 ไบต์ แต่เพิ่ม 13 ทราบว่าในจาวาสคริปต์ค่าตัวเลข-0ที่มีอยู่และมันเป็นพิเศษใส่ซองจะเท่ากับ 0 แต่เป็น1/-0 -Infinityversione นี้คืนค่า 0 หรือ 1

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)

ทดสอบ

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>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.