• Log InLog In
  • Register
Liquid`
Team Liquid Liquipedia
EDT 07:58
CEST 13:58
KST 20:58
  • Home
  • Forum
  • Calendar
  • Streams
  • Liquipedia
  • Features
  • Store
  • EPT
  • TL+
  • StarCraft 2
  • Brood War
  • Smash
  • Heroes
  • Counter-Strike
  • Overwatch
  • Liquibet
  • Fantasy StarCraft
  • TLPD
  • StarCraft 2
  • Brood War
  • Blogs
Forum Sidebar
Events/Features
News
Featured News
BGE Stara Zagora 2025: Info & Preview3Code S RO12 Preview: GuMiho, Bunny, SHIN, ByuN3The Memories We Share - Facing the Final(?) GSL42Code S RO12 Preview: Cure, Zoun, Solar, Creator4[ASL19] Finals Preview: Daunting Task30
Community News
GSL Ro4 and Finals moved to Sunday June 15th5Weekly Cups (May 27-June 1): ByuN goes back-to-back0EWC 2025 Regional Qualifier Results21Code S RO12 Results + RO8 Groups (2025 Season 2)3Weekly Cups (May 19-25): Hindsight is 20/20?0
StarCraft 2
General
BGE Stara Zagora 2025: Info & Preview EWC 2025 Regional Qualifier Results GSL Ro4 and Finals moved to Sunday June 15th The SCII GOAT: A statistical Evaluation The Memories We Share - Facing the Final(?) GSL
Tourneys
$1,200 WardiTV June (June 4th-June 15th) SOOPer7s Showmatches 2025 Weekly Cups (May 27-June 1): ByuN goes back-to-back EWC 2025 Regional Qualifiers (May 28-June 1) WardiTV Mondays
Strategy
[G] Darkgrid Layout Simple Questions Simple Answers [G] PvT Cheese: 13 Gate Proxy Robo
Custom Maps
[UMS] Zillion Zerglings
External Content
Mutation # 476 Charnel House Mutation # 475 Hard Target Mutation # 474 Futile Resistance Mutation # 473 Cold is the Void
Brood War
General
BGH auto balance -> http://bghmmr.eu/ BW General Discussion Will foreigners ever be able to challenge Koreans? Battle.net is not working Which player typ excels at which race or match up?
Tourneys
[ASL19] Grand Finals [BSL20] RO20 Group Stage [BSL20] RO20 Group D - Sunday 20:00 CET [BSL 2v2] ProLeague Season 3 - Friday 21:00 CET
Strategy
I am doing this better than progamers do. [G] How to get started on ladder as a new Z player
Other Games
General Games
Stormgate/Frost Giant Megathread Path of Exile Mechabellum Monster Hunter Wilds Nintendo Switch Thread
Dota 2
Official 'what is Dota anymore' discussion
League of Legends
LiquidLegends to reintegrate into TL.net
Heroes of the Storm
Simple Questions, Simple Answers
Hearthstone
Heroes of StarCraft mini-set
TL Mafia
Vanilla Mini Mafia TL Mafia Community Thread TL Mafia Plays: Diplomacy TL Mafia: Generative Agents Showdown Survivor II: The Amazon
Community
General
US Politics Mega-thread European Politico-economics QA Mega-thread Russo-Ukrainian War Thread Things Aren’t Peaceful in Palestine Canadian Politics Mega-thread
Fan Clubs
Maru Fan Club Serral Fan Club
Media & Entertainment
Korean Music Discussion [Manga] One Piece
Sports
NHL Playoffs 2024 Formula 1 Discussion 2024 - 2025 Football Thread NBA General Discussion
World Cup 2022
Tech Support
Computer Build, Upgrade & Buying Resource Thread Cleaning My Mechanical Keyboard How to clean a TTe Thermaltake keyboard?
TL Community
The Automated Ban List
Blogs
Heero Yuy & the Tax…
KrillinFromwales
Research study on team perfo…
TrAiDoS
I was completely wrong ab…
jameswatts
Need Your Help/Advice
Glider
Trip to the Zoo
micronesia
Poker
Nebuchad
Info SLEgma_12
SLEgma_12
Customize Sidebar...

Website Feedback

Closed Threads



Active: 16538 users

PHP - Date Format Check

Blogs > tofucake
Post a Reply
Normal
tofucake
Profile Blog Joined October 2009
Hyrule19024 Posts
Last Edited: 2010-07-23 14:31:29
July 20 2010 16:15 GMT
#1
I needed to make sure dates were in Y-m-d format for some calculations at work, so I wrote this up. It's not perfect, but it's quite enough to handle my needs. So, for anyone who uses PHP and needs to make sure dates are in Y-m-d format (for strtotime() or whatever reason), I grant you checkDateFormat(). It checks for valid formatted dates with space, hyphen, period, or slash separation.

function checkDateFormat($date, $empty = '0', $sep = '/')
{
$date = preg_replace('/[^\d\-\. \/]/', '', $date); // remove non-numeric and non-date separaters

$check = preg_split('/[ \-\.\/]/', $date);
if(empty($check)) return '0';

foreach($check as &$item)
$item = str_pad($item, 2, '0', STR_PAD_LEFT);
$date = implode('-', $check);

// matches for all format dates, with space, hyphen, period, or slash separators
// correct format needed is Y-m-d
// 100 is used as the final check to keep room open for later additions
$patterns = array(
0 => '/(9999)[- \.\/](09)[- \.\/](09)/', // one of the many different "blank" values used
1 => '/(0[1-9]|1[012])[- \.\/](0[1-9]|1[012])[- \.\/](\d{4,4})/', // unknown d-m order, Y at end
2 => '/(\d{4,4})[- \.\/](0[1-9]|1[012])[- \.\/](0[1-9]|1[012])/', // unknown d-m order, Y at front
3 => '/(0[1-9]|1[012])[- \.\/](0[1-9]|[12][0-9]|3[01])[- \.\/](\d{4,4})/', // m-d-Y
4 => '/(\d{4,4})[- \.\/](0[1-9]|1[012])[- \.\/](0[1-9]|[12][0-9]|3[01])/', // Y-m-d (aka already correct)
5 => '/(0[1-9]|[12][0-9]|3[01])[- \.\/](0[1-9]|1[012])[- \.\/](\d{4,4})/', // d-m-Y
6 => '/(\d{4,4})[- \.\/](0[1-9]|[12][0-9]|3[01])[- \.\/](0[1-9]|1[012])/', // Y-d-m
99 => '/ |[s(\302\240|\240)]+|[W]+/', // blank, empty, or placeholder
100 => '/(\d{2,2})[- \.\/](\d{2,2})[- \.\/](\d{2,2})/' // unknown all double digits
);

// for unknown d-m order assume month is first
$replace = array(
0 => $empty,
1 => "$3{$sep}$1{$sep}$2", // unknown d-m order, Y at end -> Y-m-d
2 => "$1{$sep}$2{$sep}$3", // unknown d-m order, Y at front -> Y-m-d
3 => "$3{$sep}$1{$sep}$2", // m-d-Y -> Y-m-d
4 => "$1{$sep}$2{$sep}$3", // Y-m-d -> Y-m-d
5 => "$3{$sep}$2{$sep}$1", // d-m-Y -> Y-m-d
6 => "$3{$sep}$1{$sep}$2", // Y-d-m -> Y-m-d
99 => "$0",
100 => $empty
);

foreach($patterns as $index => $pattern)
if(preg_match($pattern, $date))
return preg_replace($pattern, $replace[$index], $date);

return $empty;
}


Yeah, the regular expressions are long, but whatever. I replaced tabs with 2 spaces because it was huge (I develop with tabstop = 4, but the most common setting is 8, which is ugly).

if you want to return the original date, change $replace as follows:
100 => "$1-$2-$3"

Easy, eh?

I'll explain it more thoroughly later (ie: when I'm not at work) if anyone wants me to.

[update]
Added in checks for single digits (again, my users cannot be trusted!) and some other checks

Liquipediaasante sana squash banana
Dance.jhu
Profile Blog Joined May 2010
United States292 Posts
July 20 2010 16:46 GMT
#2
Yea, that looks right......
It is what it is...
Cambium
Profile Blog Joined June 2004
United States16368 Posts
July 20 2010 16:50 GMT
#3
More like "Regex - Date Format Check"
When you want something, all the universe conspires in helping you to achieve it.
gen.Sun
Profile Blog Joined October 2009
United States539 Posts
July 20 2010 17:00 GMT
#4
stackoverflow.com
tofucake
Profile Blog Joined October 2009
Hyrule19024 Posts
Last Edited: 2010-07-20 17:39:13
July 20 2010 17:38 GMT
#5
On July 21 2010 01:46 Dance.jhu wrote:
Yea, that looks right......

^^

On July 21 2010 01:50 Cambium wrote:
More like "Regex - Date Format Check"

Nah. Regex is a way of expressing patterns, you still need Perl/PHP/somelanguagethathandlesregex to use them. But yeah, it's more regex than PHP :X


On July 21 2010 02:00 gen.Sun wrote:
stackoverflow.com

Is that a nice way of saying "gtfo"?
Liquipediaasante sana squash banana
Louder
Profile Blog Joined September 2002
United States2276 Posts
July 20 2010 18:59 GMT
#6
What is the context of this solution - where's the data coming from? If you can't assume users are entering dates in just one format, then you can't assume they're not going to put the day the day before the month in all ambiguous dates. The clear problem here is the lack of disambiguation with m-d/d-m dates.
tofucake
Profile Blog Joined October 2009
Hyrule19024 Posts
July 20 2010 19:06 GMT
#7
True, but the data is coming from America (not really what you asked, but eh?), so dates are typically m-d-Y.

As for who's entering it, right now there's only a few people in our office, but this project will be sold to others. My code (elsewhere) checks the whole ambiguous date thing in other ways.
Liquipediaasante sana squash banana
Pryce
Profile Joined February 2009
Canada7 Posts
Last Edited: 2010-07-20 20:05:31
July 20 2010 19:58 GMT
#8
There's not really a need for such complicated logic. strtotime accepts any english date format so you could use something like:

$time = strtotime($date);
if ($time < 0) throw new Exception("Invalid Date Format: $date");
return date('Y-m-d', $time);

If you're running PHP 5.2 or newer, you can also use the DateTime class.
return new DateTime($date); // throws an exception if your date is invalid
R1CH
Profile Blog Joined May 2007
Netherlands10340 Posts
July 20 2010 20:04 GMT
#9
I don't see why checkdate() wouldn't work for this if you expect the arguments in a certain order. This seems like more of an input problem than a parsing problem.
AdministratorTwitter: @R1CH_TL
Louder
Profile Blog Joined September 2002
United States2276 Posts
July 20 2010 23:42 GMT
#10
The dates are presumably in text... only reason you would do this
gen.Sun
Profile Blog Joined October 2009
United States539 Posts
July 21 2010 01:14 GMT
#11
On July 21 2010 02:38 tofucake wrote:
Show nested quote +
On July 21 2010 02:00 gen.Sun wrote:
stackoverflow.com

Is that a nice way of saying "gtfo"?


It's just a better place to ask programming questions, it'll be both faster and better.
aers *
Profile Joined January 2009
United States1210 Posts
July 21 2010 02:18 GMT
#12
He's not asking a question, though.
tofucake
Profile Blog Joined October 2009
Hyrule19024 Posts
July 21 2010 12:02 GMT
#13
On July 21 2010 04:58 Pryce wrote:
There's not really a need for such complicated logic. strtotime accepts any english date format so you could use something like:

$time = strtotime($date);
if ($time < 0) throw new Exception("Invalid Date Format: $date");
return date('Y-m-d', $time);

If you're running PHP 5.2 or newer, you can also use the DateTime class.
return new DateTime($date); // throws an exception if your date is invalid

strtotime() is used, but it doesn't accept any format. This is used for financial transactions (well, displaying them..thousands of them), so a bunch of "Invalid Date Format: $date" displays is not acceptable.


On July 21 2010 05:04 R1CH wrote:
I don't see why checkdate() wouldn't work for this if you expect the arguments in a certain order. This seems like more of an input problem than a parsing problem.

The people inputting the dates cannot be trusted.


On July 21 2010 10:14 gen.Sun wrote:
Show nested quote +
On July 21 2010 02:38 tofucake wrote:
On July 21 2010 02:00 gen.Sun wrote:
stackoverflow.com

Is that a nice way of saying "gtfo"?


It's just a better place to ask programming questions, it'll be both faster and better.
I'm not asking a question, I'm posting a solution to a possible question. Also, I literally just forgot what I was going to say.
Liquipediaasante sana squash banana
Louder
Profile Blog Joined September 2002
United States2276 Posts
July 21 2010 16:49 GMT
#14
On July 21 2010 21:02 tofucake wrote:
Show nested quote +
On July 21 2010 04:58 Pryce wrote:
There's not really a need for such complicated logic. strtotime accepts any english date format so you could use something like:

$time = strtotime($date);
if ($time < 0) throw new Exception("Invalid Date Format: $date");
return date('Y-m-d', $time);

If you're running PHP 5.2 or newer, you can also use the DateTime class.
return new DateTime($date); // throws an exception if your date is invalid

strtotime() is used, but it doesn't accept any format. This is used for financial transactions (well, displaying them..thousands of them), so a bunch of "Invalid Date Format: $date" displays is not acceptable.


See, I just assumed that you were working with large blocks of text, because otherwise regular expressions are one of the worst ways to solve this problem. strtotime() will work with any of the date formats you test for, and will make the same assumption your code does for ambiguous month/day formats. But whatever floats your boat.
tofucake
Profile Blog Joined October 2009
Hyrule19024 Posts
July 21 2010 19:55 GMT
#15
Yeah I was using just strtotime() before, and it was returning 0 for about half the dates. When I started using my version, all the dates are formatted correctly (and all the calculations are correct).
Liquipediaasante sana squash banana
tofucake
Profile Blog Joined October 2009
Hyrule19024 Posts
July 23 2010 14:32 GMT
#16
Shameless bump! I updated my original with a few more checks. Works better since I found some more formats in the database :|
Liquipediaasante sana squash banana
konadora *
Profile Blog Joined February 2009
Singapore66155 Posts
July 23 2010 14:43 GMT
#17
php looks hard ;;
POGGERS
tofucake
Profile Blog Joined October 2009
Hyrule19024 Posts
July 23 2010 16:06 GMT
#18
It's really not. Most of that is actually Perl (which is very difficult to read if you're not used to it). The only reason I do something this complicated is because I didn't write the original stuff, and that allowed for (and does) a lot of dumb things.
Liquipediaasante sana squash banana
Dycedarg
Profile Joined July 2010
United States12 Posts
July 23 2010 18:16 GMT
#19
Is this for users to enter dates into a text box and then you check it? If so why go through this if you can just restrict the users from using text boxes and just have drop down boxes or a calendar of some sort. That way you never need to worry about bad user inputs. Its usually better to just not allow users the freedom to do anything they want because they can and WILL break it.
tofucake
Profile Blog Joined October 2009
Hyrule19024 Posts
July 23 2010 18:19 GMT
#20
Because there are already thousands upon thousands of dates in the database. I didn't write the original site, I've come in to fix it.
Liquipediaasante sana squash banana
Dycedarg
Profile Joined July 2010
United States12 Posts
July 23 2010 18:28 GMT
#21
The database doesn't follow a standard date format? That just sounds horrible...
tofucake
Profile Blog Joined October 2009
Hyrule19024 Posts
July 23 2010 20:09 GMT
#22
Yeah. "Date" fields are all varchar(12)'s.
Liquipediaasante sana squash banana
Pryce
Profile Joined February 2009
Canada7 Posts
Last Edited: 2010-07-24 05:08:38
July 24 2010 05:03 GMT
#23
On July 24 2010 03:19 tofucake wrote:
Because there are already thousands upon thousands of dates in the database. I didn't write the original site, I've come in to fix it.


You should fix the dates in the database, and change the schema to use the SQL date type for columns that are meant to store dates. The database will then constrain your inputs and outputs to be sane values (which may require some input validation logic). After that's in place, you can throw the date fixing script away, as that's the type of code that shouldn't live in production code. You'll have a hell of a time unit testing it.
Count9
Profile Blog Joined May 2009
China10928 Posts
Last Edited: 2010-07-24 06:30:14
July 24 2010 06:24 GMT
#24
I just add a MM/DD/YYYY thing next to every date entry box and write one regex to check if it's valid, just seems to make more sense.

Oh, it's already in the database LOL, that sucks. Though I'm sure there's already a date parser somewhere.

Also,
// for unknown d-m order assume month is first
is really sketchy >.>

Also also, it's generally better to just parse the date with regex then use another process to check whether the date is valid (e.g. not 99-99-9999) cause it's not very efficient to use so many alternations, which makes the regex engine backtrack quite a bit.
Cambium
Profile Blog Joined June 2004
United States16368 Posts
July 24 2010 06:35 GMT
#25
On July 24 2010 14:03 Pryce wrote:
Show nested quote +
On July 24 2010 03:19 tofucake wrote:
Because there are already thousands upon thousands of dates in the database. I didn't write the original site, I've come in to fix it.


You should fix the dates in the database, and change the schema to use the SQL date type for columns that are meant to store dates. The database will then constrain your inputs and outputs to be sane values (which may require some input validation logic). After that's in place, you can throw the date fixing script away, as that's the type of code that shouldn't live in production code. You'll have a hell of a time unit testing it.


Agreed completely, especially the production code point; this piece of code will be a nightmare to maintain down the road. I'd put the check at the php level or even JS level instead of relying on the db to throw exceptions.

The whole thing just seems completely unnecessary. After all, user stupidity is unbound, and you can't check for everything.
When you want something, all the universe conspires in helping you to achieve it.
tofucake
Profile Blog Joined October 2009
Hyrule19024 Posts
July 24 2010 12:41 GMT
#26
I have the date check function because my current assignment is to fix a particular page. Once that's done I'll have a new assignment, and I'm going to be pushing for that to be to fix some things in the database (like dates! but there are bigger problems), and then move the check from being used tens of thousands of times in processing to once to validate input before it's stored.
Liquipediaasante sana squash banana
Normal
Please log in or register to reply.
Live Events Refresh
Replay Cast
10:00
2025 GSL S2 - Ro12 Group B
CranKy Ducklings195
Liquipedia
[ Submit Event ]
Live Streams
Refresh
StarCraft 2
Lowko270
EnDerr 92
StarCraft: Brood War
Britney 65655
Calm 10679
Rain 8534
Bisu 3554
Horang2 2276
Hyuk 1030
Pusan 641
Mini 588
Larva 452
BeSt 425
[ Show more ]
EffOrt 313
Hyun 112
Dewaltoss 101
Light 89
ToSsGirL 73
Snow 71
Killer 69
sSak 57
Mong 47
JYJ31
[sc1f]eonzerg 26
Free 23
Icarus 22
Sharp 20
Barracks 18
ajuk12(nOOB) 18
Movie 14
JulyZerg 13
IntoTheRainbow 9
SilentControl 8
scan(afreeca) 8
zelot 7
HiyA 6
hero 6
Dota 2
XcaliburYe1152
420jenkins1089
Pyrionflax225
Counter-Strike
olofmeister3069
x6flipin661
Stewie2K338
allub239
markeloff91
Other Games
singsing3039
B2W.Neo635
DeMusliM368
XaKoH 149
ArmadaUGS67
Has27
QueenE10
Organizations
StarCraft 2
WardiTV196
StarCraft: Brood War
lovetv 7
StarCraft 2
Blizzard YouTube
StarCraft: Brood War
BSLTrovo
sctven
[ Show 14 non-featured ]
StarCraft 2
• Berry_CruncH283
• StrangeGG 55
• -Miszu- 8
• AfreecaTV YouTube
• intothetv
• Kozan
• IndyKCrew
• LaughNgamezSOOP
• Migwel
• sooper7s
StarCraft: Brood War
• BSLYoutube
• STPLYoutube
• ZZZeroYoutube
Other Games
• WagamamaTV298
Upcoming Events
PiGosaur Monday
12h 2m
Bellum Gens Elite
1d
The PondCast
1d 22h
Bellum Gens Elite
1d 23h
Replay Cast
2 days
Bellum Gens Elite
2 days
Replay Cast
3 days
CranKy Ducklings
3 days
SC Evo League
4 days
Bellum Gens Elite
4 days
[ Show More ]
Fire Grow Cup
4 days
CSO Contender
4 days
Replay Cast
4 days
SOOP
4 days
SHIN vs GuMiho
Sparkling Tuna Cup
4 days
AllThingsProtoss
4 days
Fire Grow Cup
5 days
Replay Cast
5 days
Replay Cast
6 days
Replay Cast
6 days
Liquipedia Results

Completed

Proleague 2025-05-28
DreamHack Dallas 2025
Heroes 10 EU

Ongoing

JPL Season 2
BSL 2v2 Season 3
BSL Season 20
KCM Race Survival 2025 Season 2
NPSL S3
Rose Open S1
CSL Season 17: Qualifier 1
CSL Season 17: Qualifier 2
2025 GSL S2
BLAST.tv Austin Major 2025
ESL Impact League Season 7
IEM Dallas 2025
PGL Astana 2025
Asian Champions League '25
ECL Season 49: Europe
BLAST Rivals Spring 2025
MESA Nomadic Masters
CCT Season 2 Global Finals
IEM Melbourne 2025
YaLLa Compass Qatar 2025
PGL Bucharest 2025
BLAST Open Spring 2025

Upcoming

CSL 17: 2025 SUMMER
Copa Latinoamericana 4
CSLPRO Last Chance 2025
CSLAN 2025
K-Championship
SEL Season 2 Championship
Esports World Cup 2025
HSC XXVII
Championship of Russia 2025
Bellum Gens Elite Stara Zagora 2025
Murky Cup #2
BLAST Bounty Fall 2025
BLAST Bounty Fall Qual
IEM Cologne 2025
FISSURE Playground #1
TLPD

1. ByuN
2. TY
3. Dark
4. Solar
5. Stats
6. Nerchio
7. sOs
8. soO
9. INnoVation
10. Elazer
1. Rain
2. Flash
3. EffOrt
4. Last
5. Bisu
6. Soulkey
7. Mini
8. Sharp
Sidebar Settings...

Advertising | Privacy Policy | Terms Of Use | Contact Us

Original banner artwork: Jim Warren
The contents of this webpage are copyright © 2025 TLnet. All Rights Reserved.