PHP Regex ที่จะตรวจสอบวันที่อยู่ในรูปแบบ YYYY-MM-DD


101

ฉันกำลังพยายามตรวจสอบว่าวันที่ที่ป้อนโดยผู้ใช้ปลายทางอยู่ใน YYYY-MM-DD Regex ไม่เคยเป็นจุดแข็งของฉันฉันได้รับค่าส่งคืนที่ผิดพลาดสำหรับ preg_match () ที่ฉันตั้งค่าไว้

ดังนั้นฉันคิดว่าฉันทำ regex ยุ่งเหยิงตามรายละเอียดด้านล่าง

$date="2012-09-12";

if (preg_match("^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$",$date))
    {
        return true;
    }else{
        return false;
    }

ความคิดใด ๆ ?


6
Regex ไม่เพียงพอที่จะตรวจสอบวันที่ หลังจาก regex คุณควรใช้หนึ่งในสองคนนี้: date("Y-m-d", strtotime("2012-09-12"))=="2012-09-12";หรือของ checkdate ( int $month , int $day , int $year )PHP
Tiberiu-Ionuț Stan

ฉันไม่ได้พยายามตรวจสอบความถูกต้องในตอนนี้ฉันแค่อยากให้แน่ใจว่ามันอยู่ในรูปแบบปปปป - ดด - วว
cosmicsafari

2
สำหรับค่าที่ผู้ใช้ป้อนจะมี "จุด" ใดที่ดีกว่าในการตรวจสอบความถูกต้องในเวลาอื่นนอกจากทันทีหลังจาก regex ในการส่งแบบฟอร์ม (เพื่อให้คุณสามารถแสดงข้อผิดพลาดได้)
Tiberiu-Ionuț Stan

จุดที่ยุติธรรมสามารถบันทึก hickup ได้ในภายหลัง
cosmicsafari

คำตอบ:


203

ลองทำตามนี้

$date="2012-09-12";

if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)) {
    return true;
} else {
    return false;
}

18
return (bool)preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date);
Tiberiu-Ionuț Stan

5
เหตุใดจึงถูกทำเครื่องหมายว่าเป็นคำตอบที่ถูกต้อง สิ่งนี้จะคืนค่าจริงสำหรับจำนวนวันที่ไม่ถูกต้องเช่น 2016-02-30 และ 2016-09-31
Graham

8
คำถามนี้เกี่ยวกับวิธีตรวจสอบรูปแบบวันที่ (ปปปป - ดด - วว) และคำตอบที่ทำเครื่องหมายว่ายอมรับไม่ใช่คำตอบที่ดีที่สุดเสมอไป แต่หมายความว่ามันใช้ได้ผลกับผู้ที่ถามอ่านทัวร์ที่สวยงามนี้: stackoverflow คอม / ทัวร์ .
stramin

@Graham โพสต์เก่าฉันรู้ แต่เห็นด้วยกับ Stramin - คำถามนี้ถามเกี่ยวกับการตรวจสอบรูปแบบ - ไม่ใช่การตรวจสอบวันที่จริง
treyBake

ตรวจสอบความถูกต้องของวันที่และเวลาล่วงหน้า ("/ ^ [0-9] {4} - (0 [1-9] | 1 [0-2]) - (0 [1-9] | [1-2] [0-9] | 3 [0-1]) ท (0 [1-9] | 1 [0-9] | 2 [0-4]) :( 0 [1-9] | 1 [0-9] | 2 [0 -9] | 3 [0-9] | 4 [0-9] | 5 [0-9] | 6 [0-9]) $ / ", $ dateTime)
Danilo Santos

101

อาจจะดีกว่าถ้าใช้กลไกอื่นสำหรับสิ่งนี้

โซลูชันที่ทันสมัยพร้อมด้วยDateTime:

$dt = DateTime::createFromFormat("Y-m-d", $date);
return $dt !== false && !array_sum($dt::getLastErrors());

สิ่งนี้จะตรวจสอบความถูกต้องของอินพุตด้วย: $dt !== falseตรวจสอบให้แน่ใจว่าสามารถแยกวิเคราะห์วันที่ตามรูปแบบที่ระบุได้และarray_sumเคล็ดลับนี้เป็นวิธีที่สั้นกว่าในการตรวจสอบว่า PHP ไม่ได้ทำการ "เลื่อนเดือน" (เช่นพิจารณาว่าวันที่ 32 มกราคมคือ 1 กุมภาพันธ์) ดูDateTime::getLastErrors()ข้อมูลเพิ่มเติม

โซลูชันโรงเรียนเก่าพร้อมexplodeและcheckdate:

list($y, $m, $d) = array_pad(explode('-', $date, 3), 3, 0);
return ctype_digit("$y$m$d") && checkdate($m, $d, $y);

สิ่งนี้ตรวจสอบว่าอินพุตเป็นวันที่ที่ถูกต้องเช่นกัน คุณสามารถทำได้ด้วย regex แน่นอน แต่มันจะยุ่งยากกว่านี้ - และวันที่ 29 กุมภาพันธ์ไม่สามารถตรวจสอบความถูกต้องด้วย regex ได้เลย

ข้อเสียเปรียบของแนวทางนี้คือคุณต้องระมัดระวังอย่างมากที่จะปฏิเสธอินพุตที่ "ไม่ดี" ที่เป็นไปได้ทั้งหมดในขณะที่ไม่ต้องแจ้งให้ทราบไม่ว่าในกรณีใด ๆ วิธีการมีดังนี้

  • explode จำกัด การส่งคืน 3 โทเค็น (ดังนั้นหากอินพุตเป็น "1-2-3-4" $dจะกลายเป็น "3-4")
  • ctype_digit ใช้เพื่อตรวจสอบให้แน่ใจว่าอินพุตไม่มีอักขระที่ไม่ใช่ตัวเลข (นอกเหนือจากขีดกลาง)
  • array_padใช้ (ด้วยค่าเริ่มต้นที่จะทำให้checkdateล้มเหลว) เพื่อให้แน่ใจว่ามีการส่งคืนองค์ประกอบเพียงพอดังนั้นหากอินพุตเป็น "1-2" list()จะไม่มีการแจ้งเตือน

+1 ใช้เสมอDateTimeและไม่เคยได้ยินเกี่ยวกับcheckdate...
k102

@ k102: DateTimeทำได้เช่นกัน ฉันเพิ่งสรุปคำตอบเสร็จแล้วลองดูอีกครั้งถ้าคุณชอบ
จอน

เมื่อดูคู่มือ PHP ดูเหมือนว่าโซลูชันแรกจะตรวจสอบวันที่ที่ไม่สมบูรณ์ (กรอกค่าที่หายไปจากวันที่ปัจจุบัน)
user2428118

ปัญหาอีกประการหนึ่งในการแก้ปัญหา # 1: "ค่าที่ไม่อยู่ที่มีอยู่เกลือกกลิ้ง" เช่น 2001-02-31 กลายเป็น 2001-03-03 (แม้ว่า OP จะไม่ได้ถามอย่างชัดเจนว่าเป็นไปไม่ได้)
user2428118

1
@ user2428118: คุณลองวิธีแก้ปัญหา # 1 ตรงตามที่ระบุหรือแค่บรรทัดแรก? คุณคลิกลิงก์ที่ฉันให้ไว้กับเอกสารประกอบgetLastErrorsหรือไม่
จอน

43

yyyy-mm-dd: /^((((19|[2-9]\d)\d{2})\-(0[13578]|1[02])\-(0[1-9]|[12]\d|3[01]))|(((19|[2-9]\d)\d{2})\-(0[13456789]|1[012])\-(0[1-9]|[12]\d|30))|(((19|[2-9]\d)\d{2})\-02\-(0[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))\-02\-29))$/g

ปปปป / mm / วว: /^((((19|[2-9]\d)\d{2})\/(0[13578]|1[02])\/(0[1-9]|[12]\d|3[01]))|(((19|[2-9]\d)\d{2})\/(0[13456789]|1[012])\/(0[1-9]|[12]\d|30))|(((19|[2-9]\d)\d{2})\/02\/(0[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))\/02\/29))$/g

mm-dd-yyyy: /^(((0[13578]|1[02])\-(0[1-9]|[12]\d|3[01])\-((19|[2-9]\d)\d{2}))|((0[13456789]|1[012])\-(0[1-9]|[12]\d|30)\-((19|[2-9]\d)\d{2}))|(02\-(0[1-9]|1\d|2[0-8])\-((19|[2-9]\d)\d{2}))|(02\-29\-((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g

mm / dd / yyyy: /^(((0[13578]|1[02])\/(0[1-9]|[12]\d|3[01])\/((19|[2-9]\d)\d{2}))|((0[13456789]|1[012])\/(0[1-9]|[12]\d|30)\/((19|[2-9]\d)\d{2}))|(02\/(0[1-9]|1\d|2[0-8])\/((19|[2-9]\d)\d{2}))|(02\/29\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g

วว / ดด / ปปปป: /^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g

วว - มม - ปปป: /^(((0[1-9]|[12]\d|3[01])\-(0[13578]|1[02])\-((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\-(0[13456789]|1[012])\-((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\-02\-((19|[2-9]\d)\d{2}))|(29\-02\-((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g


ข้างต้นทั้งหมดใช้สำหรับวันที่ 1900 ถึง 9999 ซึ่งเป็นสิ่งที่จำเป็นเกือบตลอดเวลาและสั้นกว่าความพยายามของฉัน 74 ตัวอักษร (เป็นรูปแบบ yyyy-mm-dd) หากคุณต้องการวันที่ก่อนปี 1900 การปรับแต่งเล็กน้อยสำหรับคำตอบของ Shyju จะอนุญาตตั้งแต่ปี 1,000 และอีก 23 ตัวอักษรที่สั้นกว่า: ^ ((([1-9] \ d {3}) \ - (0 [13578] | 1 [02]) \ - (0 [1-9] | [12] \ d | 3 [01])) | ((19 | [2-9] \ d) \ d {2}) \ - ( 0 [13456789] | 1 [012]) \ - (0 [1-9] | [12] \ d | 30)) | (([1-9] \ d {3}) \ - 02 \ - (0 [1-9] | 1 \ d | 2 [0-8])) | (([1-9] \ d (0 [48] | [2468] [048] | [13579] [26]) | ( (16 | [2468] [048] | [3579] [26]) 00)) \ - 02 \ -29)) $
Graham

37

เกณฑ์:

ทุกๆปีหารด้วย 4 เป็นปีอธิกสุรทินยกเว้นเมื่อหารด้วย 100 ลงตัวเว้นแต่จะหารด้วย 400 ดังนั้น:

2004 - leap year - divisible by 4
1900 - not a leap year - divisible by 4, but also divisible by 100
2000 - leap year - divisible by 4, also divisible by 100, but divisible by 400

กุมภาพันธ์มี 29 วันในปีอธิกสุรทินและ 28 วันเมื่อไม่ใช่ปีอธิกสุรทิน

30 วันในเดือนเมษายนมิถุนายนกันยายนและพฤศจิกายน

31 วันในเดือนมกราคมมีนาคมพฤษภาคมกรกฎาคมสิงหาคมตุลาคมและธันวาคม

ทดสอบ:

วันที่ต่อไปนี้ควรผ่านการตรวจสอบความถูกต้อง:

1976-02-29
2000-02-29
2004-02-29
1999-01-31

วันที่ต่อไปนี้ควรตรวจสอบไม่ผ่านทั้งหมด:

2015-02-29
2015-04-31
1900-02-29
1999-01-32
2015-02-00

พิสัย:

เราจะทดสอบวันที่ตั้งแต่ 1 มกราคม 1000 ถึง 31 ธันวาคม 2999 ใน ทางเทคนิคแล้วปฏิทินเกรกอเรียนที่ใช้ในปัจจุบันเริ่มใช้เฉพาะในปี 1753 สำหรับจักรวรรดิอังกฤษและในปี 1600 สำหรับประเทศต่างๆในยุโรป แต่ฉันจะไม่ กังวลเกี่ยวกับเรื่องนั้น

Regex เพื่อทดสอบปีอธิกสุรทิน:

ปีหารด้วย 400:

1200|1600|2000|2400|2800
can be shortened to:
(1[26]|2[048])00

if you wanted all years from 1AD to 9999 then this would do it:
(0[48]|[13579][26]|[2468][048])00
if you're happy with accepting 0000 as a valid year then it can be shortened:
([13579][26]|[02468][048])00

ปีหารด้วย 4:

[12]\d([02468][048]|[13579][26])

ปีหารด้วย 100:

[12]\d00

หารด้วย 100 ไม่ลงตัว:

[12]\d([1-9]\d|\d[1-9])

ปีหารด้วย 100 แต่ไม่หาร 400:

((1[1345789])|(2[1235679]))00

หารด้วย 4 แต่ไม่หารด้วย 100:

[12]\d([2468][048]|[13579][26]|0[48])

ปีอธิกสุรทิน:

divisible by 400 or (divisible by 4 and not divisible by 100)
((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48])

หารด้วย 4 ไม่ลงตัว:

[12]\d([02468][1235679]|[13579][01345789])

ไม่ใช่ปีอธิกสุรทิน:

Not divisible by 4 OR is divisible by 100 but not by 400
([12]\d([02468][1235679]|[13579][01345789]))|(((1[1345789])|(2[1235679]))00)

เดือนและวันที่ถูกต้องไม่รวมกุมภาพันธ์ (MM-DD):

((01|03|05|07|08|10|12)-(0[1-9]|[12]\d|3[01]))|((04|06|09|11)-(0[1-9]|[12]\d|30))
shortened to:
((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30))

กุมภาพันธ์มี 28 วัน:

02-(0[1-9]|1\d|2[0-8])

กุมภาพันธ์ 29 วัน:

02-(0[1-9]|[12]\d)

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

(leap year followed by (valid month-day-excluding-february OR 29-day-february)) 
OR
(non leap year followed by (valid month-day-excluding-february OR 28-day-february))

((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8]))))

ดังนั้นคุณจึงมี regex สำหรับวันที่ระหว่าง 1 มกราคม 1000 ถึง 31 ธันวาคม 2999 ในรูปแบบ YYYY-MM-DD

ฉันสงสัยว่ามันอาจจะสั้นลงไปหน่อย แต่ฉันจะปล่อยให้คนอื่นไป

ซึ่งจะตรงกับวันที่ที่ถูกต้องทั้งหมด หากคุณต้องการให้ใช้งานได้ก็ต่อเมื่อมีวันที่เพียงวันเดียวและไม่มีสิ่งอื่นใดให้ห่อไว้^( )$ดังนี้:

^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$

หากคุณต้องการสำหรับรายการวันที่ที่เป็นทางเลือก (เช่นอาจเป็นวันที่ว่างหรือวันที่ที่ถูกต้อง) ให้เพิ่ม^$|ที่จุดเริ่มต้นดังนี้:

^$|^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$

8
นั่นคือการแสดงออกที่กล้าหาญและอธิบายได้เป็นอย่างดี
โดยรอบ

คุณมีหลักฐานที่ชัดเจนว่าจะผ่านทุกกรณีที่ถูกต้องและล้มเหลวในทุกกรณีที่ไม่ถูกต้อง?
Md Ashraful อิสลาม

@Md Ashraful Islam No
Graham

@Graham Altough ไม่มีปัญหาเรากำลังใช้มันในเว็บไซต์ของเรา ฉันหวังว่าจะไม่มีปัญหาเกิดขึ้น
Md Ashraful Islam

@Md Ashraful Islam - เรายังใช้มันและไม่เคยมีปัญหาใด ๆ กับมัน
Graham

18

คุณสามารถทำได้ด้วยวิธีนี้:

if (preg_match("/\d{4}\-\d{2}-\d{2}/", $date)) {
    echo 'true';
} else {
    echo 'false';
}

แต่คุณควรใช้อันนี้ดีกว่า:

$date = DateTime::createFromFormat('Y-m-d', $date);
if ($date) {
    echo $date -> format('Y-m-d');
}

ในกรณีนี้คุณจะได้วัตถุที่ใช้งานง่ายกว่าสตริงเพียงอย่างเดียว


2
เทคนิค dateTime ที่ใช้ที่นี่จะคืนค่าจริงสำหรับวันที่เช่น 2016-05-44 ซึ่งไม่ใช่วันที่จริง
nonybrighto

นี่ไม่ใช่ตัวอย่างที่ดีโดยเฉพาะหากคุณต้องการได้รับวันที่ (Ymd) ตัวอย่าง: 0175-44-19927จะผ่านไป
Attila Naghi

7

ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันคิดว่าฉันมีทางออกที่ดี

$date = "2016-02-21";
$format = "Y-m-d";

if(date($format, strtotime($date)) == date($date)) {
    echo "true";
} else {
    echo "false";
}

คุณสามารถลอง หากคุณเปลี่ยนวันที่เป็น 21.02.2016 เสียงสะท้อนเป็นเท็จ และถ้าคุณเปลี่ยนรูปแบบหลังจากนั้นเป็น dmY เสียงสะท้อนจะเป็นจริง

ด้วยรหัสง่าย ๆ นี้คุณจะสามารถตรวจสอบได้ว่ารูปแบบวันที่ใดถูกใช้โดยไม่ต้องตรวจสอบโดย regex

อาจจะมีผู้ที่จะทดสอบในทุกกรณี แต่ฉันคิดว่าความคิดของฉันใช้ได้โดยทั่วไป สำหรับฉันดูเหมือนว่ามีเหตุผล


ฉันไม่คิดว่าคุณต้องการ date () ประมาณ $ date ในบรรทัด if ถ้า (วันที่ (รูปแบบ $, strtotime ($ date)) == $ วันที่) - ควรเพียงพอ
iateadonut

7

คุณสามารถใช้ preg_match กับฟังก์ชัน php checkdate

$date  = "2012-10-05";
$split = array();
if (preg_match ("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date, $split))
{
    return checkdate($split[2], $split[3], $split[1]);
}

return false;

ส่งคืน preg_match ("/ ^ ([0-9] {4}) - ([0-9] {2}) - ([0-9] {2}) $ /", $ date, $ split)) && checkdate ($ แยก [2], $ แยก [3], $ แยก [1]);
Tiberiu-Ionuț Stan

5

preg_match ต้องการ a / หรือถ่านอื่นเป็นตัวคั่น

preg_match("/^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$/",$date)

คุณควรตรวจสอบความถูกต้องของวันที่นั้นด้วยเพื่อที่คุณจะได้ไม่ต้องลงเอยด้วย 9999-19-38

bool checkdate ( int $month , int $day , int $year )

3

คุณสามารถทำได้เช่นนี้:

if (DateTime::createFromFormat('Y-m-d', $date)->format('Y-m-d') === $date) {

    // date is correctly formatted and valid, execute some code

}

สิ่งนี้จะไม่เพียงแค่ตรวจสอบรูปแบบเท่านั้น แต่ยังรวมถึงความถูกต้องของวันที่ด้วยตัวเองด้วยเนื่องจากDateTimeจะสร้างเฉพาะวันที่ที่ถูกต้องและสิ่งนี้จะต้องตรงกับข้อมูลที่ป้อน


3

คุณสามารถใช้ได้

function validateDate($date, $format = 'Y-m-d H:i:s')
{
    $d = DateTime::createFromFormat($format, $date);
    return $d && $d->format($format) == $date;
}

$date="2012-09-12";    
echo validateDate($date, 'Y-m-d'); // true or false

2

ตรวจสอบและตรวจสอบYYYY-MM-DDวันที่ในคำสั่งบรรทัดเดียว

function isValidDate($date) {
    return preg_match("/^(\d{4})-(\d{1,2})-(\d{1,2})$/", $date, $m)
        ? checkdate(intval($m[2]), intval($m[3]), intval($m[1]))
        : false;
}

ผลลัพธ์จะเป็น:

var_dump(isValidDate("2018-01-01")); // bool(true)
var_dump(isValidDate("2018-1-1"));   // bool(true)
var_dump(isValidDate("2018-02-28")); // bool(true)
var_dump(isValidDate("2018-02-30")); // bool(false)

อนุญาตให้ใช้วันและเดือนที่ไม่มีศูนย์นำหน้า หากคุณไม่ต้องการอนุญาตสิ่งนี้ regexp ควรเป็น:

"/^(\d{4})-(\d{2})-(\d{2})$/"

2

อาจเป็นประโยชน์กับใครบางคน:

$patterns = array(
            'Y'           =>'/^[0-9]{4}$/',
            'Y-m'         =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])$/',
            'Y-m-d'       =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])$/',
            'Y-m-d H'     =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])\s(0|[0-1][0-9]|2[0-4])$/',
            'Y-m-d H:i'   =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])\s(0|[0-1][0-9]|2[0-4]):?(0|[0-5][0-9]|60)$/',
            'Y-m-d H:i:s' =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])\s(0|[0-1][0-9]|2[0-4]):?((0|[0-5][0-9]):?(0|[0-5][0-9])|6000|60:00)$/',
        );
echo preg_match($patterns['Y'], '1996'); // true
echo preg_match($patterns['Y'], '19966'); // false
echo preg_match($patterns['Y'], '199z'); // false
echo preg_match($patterns['Y-m'], '1996-0'); // false
echo preg_match($patterns['Y-m'], '1996-09'); // true
echo preg_match($patterns['Y-m'], '1996-1'); // true
echo preg_match($patterns['Y-m'], '1996/1'); // true
echo preg_match($patterns['Y-m'], '1996/12'); // true
echo preg_match($patterns['Y-m'], '1996/13'); // false
echo preg_match($patterns['Y-m-d'], '1996-11-1'); // true
echo preg_match($patterns['Y-m-d'], '1996-11-0'); // false
echo preg_match($patterns['Y-m-d'], '1996-11-32'); // false
echo preg_match($patterns['Y-m-d H'], '1996-11-31 0'); // true
echo preg_match($patterns['Y-m-d H'], '1996-11-31 00'); // true
echo preg_match($patterns['Y-m-d H'], '1996-11-31 24'); // true
echo preg_match($patterns['Y-m-d H'], '1996-11-31 25'); // false
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 2400'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:00'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:59'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:60'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:61'); // false
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:61'); // false
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:6000'); // true
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:60:00'); // true
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:59:59'); // true
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:59:60'); // false
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:60:01'); // false

'1996-11-31 24:00'); // true, จริงเหรอ? ยิ่งไปกว่านั้นบางครั้งอาจมีเวลา 61 วินาทีในหนึ่งนาทีโปรดดูที่: en.wikipedia.org/wiki/Leap_second
Toto

1

หากคุณต้องการจับคู่วันที่ประเภทนั้นให้ใช้:

preg_match("~^\d{4}-\d{2}-\d{2}$~", $date)

1

สิ่งนี้จะบอกคุณได้ว่ารูปแบบถูกต้องหรือไม่และวันที่ป้อนข้อมูลถูกต้องหรือไม่

    $datein = '2012-11-0';

    if(preg_match('/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $datein)){
        echo 'good';
    }else{
        echo 'no good';
    }

1

หากต้องการความช่วยเหลือใด ๆ นี่คือ regex สำหรับรูปแบบ jnY (ปีต้องมากกว่า 2018):

if (preg_match('/^([1-9]|[1-2][0-9]|[3][0-1])\-([1-9]|[1][0-2])\-(?:20)([1][8-9]|[2-9][0-9])$/', $date)) {
   // Do stuff
}

1

รูปแบบ 1: $ format1 = "2012-12-31";

รูปแบบ 2: $ format2 = "31-12-2012";

if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$format1)) {
    return true;
} else {
    return false;
}

if (preg_match("/^(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-[0-9]{4}$/",$format2)) {
    return true;
} else {
    return false;
}

1

ฟังก์ชั่นตรวจสอบความถูกต้องของรูปแบบวันที่ทั่วไป:

function validateDate($date, $format = 'Y-m-d') {
  $d = DateTime::createFromFormat($format, $date);
  return $d && $d->format($format) == $date;
}

ตัวอย่างการดำเนินการ:

var_dump(validateDate('2021-02-28')); // true
var_dump(validateDate('2021-02-29')); // false

โปรดใส่คำตอบของคุณในบริบทเสมอแทนที่จะวางโค้ด ดูที่นี่สำหรับรายละเอียดเพิ่มเติม โปรดแก้ไขคำตอบของคุณเพื่อให้มีทุกส่วนของโค้ดในบล็อก markdown
gehbiszumeis

0

ทุกอย่างขึ้นอยู่กับว่าคุณต้องการให้ฟังก์ชันนี้เข้มงวดเพียงใด ตัวอย่างเช่นหากคุณไม่ต้องการให้เดือนที่สูงกว่า 12 และวันที่สูงกว่า 31 (ไม่ขึ้นอยู่กับเดือนที่ต้องเขียนวันที่ - ลอจิก) มันอาจจะค่อนข้างซับซ้อน:

function checkDate($date)
{
  $regex = '/^' . 
    '(' .

    // Allows years 0000-9999
    '(?:[0-9]{4})' .
    '\-' .

    // Allows 01-12
    '(?:' .
    '(?:01)|(?:02)|(?:03)|(?:04)|(?:05)|(?:06)|(?:07)|(?:08)|(?:09)|(?:10)|' .
    '(?:11)|(?:12)' .
    ')' .
    '\-' .

    // Allows 01-31
    '(?:' .
    '(?:01)|(?:02)|(?:03)|(?:04)|(?:05)|(?:06)|(?:07)|(?:08)|(?:09)|(?:10)|' .
    '(?:11)|(?:12)|(?:13)|(?:14)|(?:15)|(?:16)|(?:17)|(?:18)|(?:19)|(?:20)|' .
    '(?:21)|(?:22)|(?:23)|(?:24)|(?:25)|(?:26)|(?:27)|(?:28)|(?:29)|(?:30)|' .
    '(?:31)' .
    ')' .

    '$/';

  if ( preg_match($regex, $date) ) {
    return true;
  }

  return false;
}

$result = checkDate('2012-09-12');

โดยส่วนตัวแล้วฉันจะไปเพื่อ: /^([0-9]{4}\-([0-9]{2}\-[0-9]{2})$/


4
นิพจน์ทั่วไปนี้ซับซ้อนโดยไม่จำเป็น 0[1-9]|1[0-2]ตรงกับเดือน 01-12 และ0[1-9]|[12][0-9]|3[01]ตรงกับวันที่ 01-31
estrar

ขอโทษในขณะที่ฉันอาเจียน
AlxVallejo

0

ในการทำงานกับวันที่ใน php คุณควรปฏิบัติตามมาตรฐาน php ดังนั้น regex ที่กำหนดจะทำให้มั่นใจได้ว่าคุณมีวันที่ที่ถูกต้องซึ่งสามารถทำงานกับ PHP ได้

    preg_match("/^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)

rgex ของคุณผิดมันจะไม่ตรงกัน1980-01-01แต่จะตรงกัน2100-02-29
Toto

0

วิธีนี้มีประโยชน์ในการตรวจสอบวันที่ใน PHP วิธีปัจจุบันใช้สำหรับรูปแบบ mm / dd / yyyy คุณต้องปรับปรุงลำดับพารามิเตอร์ในcheckdateตามรูปแบบและตัวคั่นของคุณในการระเบิด

    function isValidDate($dt)
    {
        $dtArr = explode('/', $dt);
        if (!empty($dtArr[0]) && !empty($dtArr[1]) && !empty($dtArr[2])) {
            return checkdate((int) $dtArr[0], (int) $dtArr[1], (int) $dtArr[2]);
        } else {
            return false;
        }
    }

0

[หากคุณใช้ Symfony 4.1.2 ให้ลองใช้] [1]

  $validDate = explode("-",$request->get('date'));
        if (checkdate(filter_var($validDate[1],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[0],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[2],FILTER_SANITIZE_NUMBER_INT))){
            $date = date_create(filter_var($request->get('date'),FILTER_SANITIZE_SPECIAL_CHARS));
        }else{
            return $this->redirectToRoute('YOUR_ROUTE');
        }

0

จาก Laravel 5.7 และรูปแบบวันที่เช่น 31/12/2019

function checkDateFormat(string $date): bool
{
    return preg_match("/^(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])\/[0-9]{4}$/", $date);
}

0

ฉันกำลังค้นหา "วิธีตรวจสอบวันที่" และพบโซลูชันนี้เก่า แต่ฉันจะแชร์วิธีการด้านล่างที่สามารถใช้ตรวจสอบวันที่ใน php

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