(You may disregard my earlier posted codes for this function if you want)
This is just another go at the dates issue, nothing revolutionary, but some functionality you probably never knew you wanted :lol:
Some improvements.
You can now insert month as the month's name, like "10th of january1970" or "10jan70".
There are also now better restrictions on day of month, so you can not insert "300270" anymore (february never has 30 days).
And some improvements to how century is calculated, if it is not entered.
<long_description rel=additional>
While messing around with the advanced search, I found it didn't work properly when you insert from- and to-dates. First I thought it could be something somehow related to my function zen_date_raw, since it was the date-thing that failed. So I started by looking at the function zen_checkdate, which is used by the advanced search. The first thing I thought was that the function was really messy, but it also had some nice functionality; it tries to convert abbreviated month names into the appropriate number. This means you could enter for instance "12feb2005" and it should return "20050212" (except the original function would need slashes as separators). So I took that idea and remade it so it depends on another constant. This way, you can have abbreviated month names for each language!
</long_description rel=additional>
The advanced search failure was a bug (not related to this function), and it was
solved by McAjvar (is that pronounced "MacGyver"? :D):
The 2 variables $dfrom_to_check and $dto_to_check should be changed to $dfrom and $dto. You can find them in the file
includes/blocks/blk_advanced_search_result.php
on line 138 and 142.
What to do:
1.
Add the following line somewhere. Perhaps in includes/languages/<language>.php.
define('MONTH_ABBR', 'jan feb mar apr may jun jul aug sep oct nov dec');
- (optional)
Edit the following line, also in includes/languages/<language>.php, to whatever you like (as long as d, m and y is a part of it.)
define('DATE_FORMAT', 'd/m-Y');
Replace the old function zen_date_raw (still includes/languages/<language>.php)
function zen_date_raw($date, $reverse = false) {
if ($reverse) {
return substr($date, 3, 2) . substr($date, 0, 2) . substr($date, 6, 4);
} else {
return substr($date, 6, 4) . substr($date, 0, 2) . substr($date, 3, 2);
}
}
with this one:
function zen_date_raw($date, $reverse = false) {
$date = strtolower($date);
/* The second " " adds a value before MONTH_ABBR, so the first string in constant MONTH_ABBR starts at $month_abbr[1], and not $month_abbr[0] */
$month_abbr = explode(" ", " " . MONTH_ABBR);
/* In case there are more than 1 string in $month_abbr that matches $date, take the first one.
But in case one of the strings in $month_abbr should coincidentially be a part of the
non-abbreviated month name of another string in $month_abbr, we can't just take the first occurance
of the first matching string.
This is for allowing people to enter the full name of the month, like "January". Now say that in some language,
barxyz means january, while foobar means february. If the inserted month was foobar, then the returned month
would be january (because the loop starts with january and finds bar in the string, and bar is an abbreviation for barxyz (january)), while we really wanted february (foobar).
We could do it simple and depend on separators to separate day, month and year, but we don't want that. */
for ($i=1; $i < count($month_abbr); $i++) {$month_strpos[$i]=strpos($date, $month_abbr[$i]); if (is_int($month_strpos[$i]) && !isset($first_case)) {$first_case=$month_strpos[$i]; $m=$i;}; if (is_int($month_strpos[$i]) && $month_strpos[$i] < $first_case) {$first_case=$month_strpos[$i]; $m=$i;};};
if (isset($m) && isset($first_case)) {$date = substr_replace($date, $m, $first_case, 0);};
/* Now, as we've converted any eventual month strings into a number, remove non-numeric characters. */
$date = ereg_replace("[^0-9]","", $date);
/* For the date format, remove all characters except d, m and y. */
$dformat = ereg_replace("[^dmy]","", strtolower(DATE_FORMAT));
/* Define regex for day, month and year. */
$dd="([0-2][1-9]|[1-3][0-1]|[1-9])";
if (isset($m) && isset($first_case)) {$mm="(" . $m . ")";} else {$mm="(0?[1-9]|1[0-2])";};
$yyyy="((19|20)?[0-9]{2})";
/* Look at the set date format, and create the entire regex line as well as set the location where day, month and year is to be found for later reference. */
if ($dformat=="dmy") {$regexp=$dd . $mm . $yyyy; $d="2"; $m="3"; $y="4";}
else if ($dformat=="mdy") {$regexp=$mm . $dd . $yyyy; $d="3"; $m="2"; $y="4";}
else if ($dformat=="ydm") {$regexp=$yyyy . $dd . $mm; $d="4"; $m="5"; $y="2";}
else {$regexp=$yyyy . $mm . $dd; $d="5"; $m="4"; $y="2";}
/* Do the magic or return false. */
if (!ereg("(^" . $regexp . "$)", $date, $regs)) {return false;};
/* If some values are too short, fix them. */
/* fix value of day */
if (strlen($regs[$d])=="1") {$regs[$d]="0" . $regs[$d];}
/* fix value of month */
if (strlen($regs[$m])=="1") {$regs[$m]="0" . $regs[$m];}
/* fix value of year. If year is less than or equal to the last 2 numbers of the current year, set century to 20. */
if (strlen($regs[$y])=="2") {if ($regs[$y] <= (date(y))) {$regs[$y]="20" . $regs[$y];} else {$regs[$y]="19" . $regs[$y];}}
/* Find maximum number of days in the current month, and make sure the day inserted is not higher. */
/* Is month one of january, march, may, july, august, october or december? */
if ($regs[$m]=="01" || $regs[$m]=="03" || $regs[$m]=="05" || $regs[$m]=="07" || $regs[$m]=="08" || $regs[$m]=="10" || $regs[$m]=="12") {$no_of_days = "31";}
/* Is month one of april, june, september or november? */
else if ($regs[$m]=="04" || $regs[$m]=="06" || $regs[$m]=="09" || $regs[$m]=="11") {$no_of_days = "30";}
/* So the month is february, but is it a leap year? */
else if (($regs[$y] % 4) == 0) {$no_of_days = "29";}
else {$no_of_days = "28";};
/* If the day is higher than what is allowed, it's obviously not a correct date. */
if ($regs[$d] > $no_of_days) {return false;};
/* Allow dates only into the next year. (Think new year's eve and different time-zones and even possibly wrong local time set.) */
if ($regs[$y] > date(Y)+1) {return false;};
/* Return date like ddmmyyyy (reverse) or the standard yyyymmdd? */
if ($reverse) {
$date=$regs[$d] . $regs[$m] . $regs[$y];
} else {
$date=$regs[$y] . $regs[$m] . $regs[$d];
}
return $date;
}
OR if you're not interested in those comments, you may remove them if you want. Wait, let me do it for you:
function zen_date_raw($date, $reverse = false) {
$date = strtolower($date);
$month_abbr = explode(" ", " " . MONTH_ABBR);
for ($i=1; $i < count($month_abbr); $i++) {$month_strpos[$i]=strpos($date, $month_abbr[$i]); if (is_int($month_strpos[$i]) && !isset($first_case)) {$first_case=$month_strpos[$i]; $m=$i;}; if (is_int($month_strpos[$i]) && $month_strpos[$i] < $first_case) {$first_case=$month_strpos[$i]; $m=$i;};};
if (isset($m) && isset($first_case)) {$date = substr_replace($date, $m, $first_case, 0);};
$date = ereg_replace("[^0-9]","", $date);
$dformat = ereg_replace("[^dmy]","", strtolower(DATE_FORMAT));
$dd="([0-2][1-9]|[1-3][0-1]|[1-9])";
if (isset($m) && isset($first_case)) {$mm="(" . $m . ")";} else {$mm="(0?[1-9]|1[0-2])";};
$yyyy="((19|20)?[0-9]{2})";
if ($dformat=="dmy") {$regexp=$dd . $mm . $yyyy; $d="2"; $m="3"; $y="4";}
else if ($dformat=="mdy") {$regexp=$mm . $dd . $yyyy; $d="3"; $m="2"; $y="4";}
else if ($dformat=="ydm") {$regexp=$yyyy . $dd . $mm; $d="4"; $m="5"; $y="2";}
else {$regexp=$yyyy . $mm . $dd; $d="5"; $m="4"; $y="2";}
if (!ereg("(^" . $regexp . "$)", $date, $regs)) {return false;};
if (strlen($regs[$d])=="1") {$regs[$d]="0" . $regs[$d];}
if (strlen($regs[$m])=="1") {$regs[$m]="0" . $regs[$m];}
/* If year is less than or equal to the last 2 numbers of the current year, set century to 20. */
if (strlen($regs[$y])=="2") {if ($regs[$y] <= (date(y))) {$regs[$y]="20" . $regs[$y];} else {$regs[$y]="19" . $regs[$y];}}
if ($regs[$m]=="01" || $regs[$m]=="03" || $regs[$m]=="05" || $regs[$m]=="07" || $regs[$m]=="08" || $regs[$m]=="10" || $regs[$m]=="12") {$no_of_days = "31";}
else if ($regs[$m]=="04" || $regs[$m]=="06" || $regs[$m]=="09" || $regs[$m]=="11") {$no_of_days = "30";}
else if (($regs[$y] % 4) == 0) {$no_of_days = "29";}
else {$no_of_days = "28";};
if ($regs[$d] > $no_of_days) {return false;};
if ($regs[$y] > date(Y)+1) {return false;};
if ($reverse) {
$date=$regs[$d] . $regs[$m] . $regs[$y];
} else {
$date=$regs[$y] . $regs[$m] . $regs[$d];
}
return $date;
}
- (optional)
Edit
admin-> configuration-> minimum values-> date of birth
to 4.
Examples: (when DATE_FORMAT is set to 'dmy', and the current year is 2005)
1111 -> 19110101
2180 -> 19800102
1011 -> false (there is no 0 month)
11106 -> 19060111
10105 -> 20050110
1011980 -> 19800110
30/04-1904 -> 19040430
31/04-1904 -> false (april doesn't have 31 days)
1dec70 -> 19701201
29feb2000 -> 20000229
29feb2001 -> false (not leap year)
10feb january mar 75 -> 19750210
30january feb march 02 -> 20020130
abc1feb.foo-ary/\82xyz -> 19820201
Don't worry about the examples being "day, month year", it depends on what DATE_FORMAT is set to in includes/languages/<language>.php.
Enjoy B)