I’m trying to create a function that could get a date in different formats and (languages) and transform it to DD-MM-YYYY. For example, this function could get 22 Fev 2011 (Portuguese) and also 22 Feb 2011 (English). For both it should return 22-02-2011.
Let’s assume that I have a limited amount of languages, so I can have some kind of data structure that carries the months and shortens of those. My question is: “Assuming that strtotime works for English strings, what is my best choice for creating a function that given a string of a date in a language X, returns a date with the format DD-MM-YYY?”
Date/time manipulation sure is a pain. 🙂
Proposed solution
1. Locale data
I just paid a visit to Yii’s svn repository and shamelessly copied these:
2. Brute forcing the problem
Assuming that your app isn’t spending all its time converting human-readable dates, speed shouldn’t really matter. Therefore I went for a shortish solution with good extensibility, at the cost of not trying to optimize and being slightly cryptic.
That inner
foreachdoes look smelly, but I think it’s acceptable. What it does is try to replace any substring that looks like one of the items inside the sub-array of$localeInfo(current locale being tested) identified by the indexes$keys[0]and$keys[1]. To make the replacement as tersely as possible it uses an auxiliary array$flippedandpreg_replacein evaluation mode; if you don’t like this kind of code, it can certainly be replaced with a more familiar loop-based approach.3. How to use it
4. What’s with the third argument?
Well, it would be nice if the replacement worked in a case-insensitive manner. The problem with this is that you can’t blindly use
strtolowerand the/iregex modifier, because at least the former will not work unless you change theLC_TEXTlocale which is a painful requirement and not reliable to boot (locale names are OS-dependent). And the shotgun argument is that even if everything goes well that far, you still need to have your locale data saved in an ANSI encoding (which means you can’t save them all in the same file).Therefore the caller has the option of supplying their own normalization function if needed;
mb_strtolowerwould be an excellent choice here if your data is saved in UTF-8.5. Does that even work?
Sure it does.
6. And there are no caveats?
Well, apart from the normalization function there is one more I can think of:
strtotimeinternally uses the local timezone to convert the parsed date to a timestamp. This means that a date in e.g. French will be parsed correctly given the appropriate locale data, but the timestamp will be produced for the local time zone, not CET/CEST (the timezone France uses). Depending on your requirements, you might also want to account for the timezone difference.