Zen Cart Logo
Forums / Zen Cart Code Suggestions / International Date Formats

International Date Formats

Locked

Views: 11,827

Results 1 to 20 of 71
This thread is locked. New replies are disabled.
2 Feb 2005, 2:38 AM
#1
dwno avatar

dwno

Totally Zenned

Join Date:
Jan 2005
Posts:
1,285
Plugin Contributions:
0

International Date Formats

As requested to avoid confusion, here's a new and (so far) clean thread on how to set the date format to something else than the default month/day/year.

We'll start with date of birth under registration/my account, and then continue with entering dates in the advanced search form. And speaking of the search form, here's how to edit the AND and OR search operators to your specific language.

You can also now enter dates with month names, you don't need to separate numbers with slashes anymore (though you can still do that if you want), and you don't need to specify the century. For instance, when DATE_FORMAT is set to 'd,m,y', "27th of february 82" means "19820227", and "2jan05" means "20050102" (05 here doesn't mean 1905, because january the second 1905 is more than 100 years ago.).

I believe this makes entering dates much more fool-proof.

Further examples: (when DATE_FORMAT is set to 'dmy', and the current date is 2005.02.02)
2180 -> 19800102
1011 -> false (there is no 0 month)
11106 -> 19060111 (1906 and not 2006 because 1906 is less than 100 years ago)
10105 -> 20050110 (2005 and not 1905 because 10th of january 1905 is more than 100 years ago)
2011980 -> 19800110 (20th of january and not the second of january, because when day and month are only 3 digits, month will get 1 and day will get 2)
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 (when several months are named - yes, I know it's silly, but there's a reason for this example too - the first one will be taken)
abc1feb.foo-ary/\82xyz -> 19820201 (all non-digit characters will be removed after parsing for month name)

Don't worry about the examples being "day, month year", it depends on what DATE_FORMAT is set to in includes/languages/<language>.php.


Date of birth.

Here's how to do it:

Go to the admin area and edit
admin-> configuration-> minimum values-> date of birth
set it to 4.

Replace the old function

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 the following code

/* If MONTH_ABBR is not set, the function will try to find the proper month names anyway, by looking at the set locale */
define('MONTH_ABBR', 'jan feb mar apr may jun jul aug sep oct nov dec');

// Heavily modified version of zen_date_raw() for language-specific date format etc.
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] */
if ((defined('MONTH_ABBR'))AND(constant('MONTH_ABBR'))) {$month_abbr = explode(" ", " " . strtolower(MONTH_ABBR));}
else {for ($i=1; $i < 13; $i++) {$month_abbr[$i] = strtolower(strftime("%b",strtotime("$i/1/2004")));}}
for ($i=1; $i < 13; $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 (date("L", strtotime($regs[$y]."0101"))) {$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;};

/* 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;
}
  1. (optional - This is probably already done in your language files.)
    To set the date format, look for the line
define('DATE_FORMAT', 'm/d/Y');

inside includes/languages/<language>.php and change it to suit your needs.

That's it.


For reference, here's the old thread.

If you don't know how to set your locale correctly, here's how:

In the file inside includes/languages/<language>.php,
look for the line

@setlocale(LC_TIME, 'en_US');
``` (or similar) 
and set it to the proper locale.

To find out your *nix server's availible locales, try to add this code to a test file and run it: ```
<?php
echo "<br />Locales availible on this server are:<br />";
system('locale -a'); // will list all locales availible on your server
echo "<hr><br />English locales availible on this server are:<br />";
system('locale -a | grep en'); // will list all locales that contains "en" availible on your server
?>

To find out your windows server's availible locales, see this article.

For more info on setlocale(), read the manual.

2 Feb 2005, 2:40 AM
#2
dwno avatar

dwno

Totally Zenned

Join Date:
Jan 2005
Posts:
1,285
Plugin Contributions:
0

Re: International Date Formats

Advanced search form

With minor adjustments of the previous function zen_date_raw, I could replace the function zen_checkdate as well.
This will allow the same date formats as the above examples for the advanced search form.

Here's what to do:

  1. (optional)
    SKIP THIS ONE IF YOU FOLLOWED THE FIRST POST
    If you did not follow the instructions in the post above, add the following lines in includes/languages/<language>.php (or somewhere else it gets included)
/* If MONTH_ABBR is not set, the function will try to find the proper month names anyway, by looking at the set locale */
define('MONTH_ABBR', 'jan feb mar apr may jun jul aug sep oct nov dec');

edit includes/modules/pages/advanced_search_result/header_php.php,

replace line 61

if (!zen_checkdate($dfrom, DOB_FORMAT_STRING, $dfrom_array)) {

with

if (!zen_checkdate($dfrom, $dfrom_string)) {

and replace line 70

if (!zen_checkdate($dto, DOB_FORMAT_STRING, $dto_array)) {

with

if (!zen_checkdate($dto, $dto_string)) {

then you may replace line 79

if (mktime(0, 0, 0, $dfrom_array[1], $dfrom_array[2], $dfrom_array[0]) > mktime(0, 0, 0, $dto_array[1], $dto_array[2], $dto_array[0])) {

with

if ($dfrom_string > $dto_string) {

edit includes/functions/functions_general.php (line 403-491)

replace

////
// Check date
 function zen_checkdate($date_to_check, $format_string, &$date_array) {
  $separator_idx = -1;

  $separators = array('-', ' ', '/', '.');
  $month_abbr = array('jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec');
  $no_of_days = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

  $format_string = strtolower($format_string);

  if (strlen($date_to_check) != strlen($format_string)) {
   return false;
  }

  $size = sizeof($separators);
  for ($i=0; $i<$size; $i++) {
   $pos_separator = strpos($date_to_check, $separators[$i]);
   if ($pos_separator != false) {
    $date_separator_idx = $i;
    break;
   }
  }

  for ($i=0; $i<$size; $i++) {
   $pos_separator = strpos($format_string, $separators[$i]);
   if ($pos_separator != false) {
    $format_separator_idx = $i;
    break;
   }
  }

  if ($date_separator_idx != $format_separator_idx) {
   return false;
  }

  if ($date_separator_idx != -1) {
   $format_string_array = explode( $separators[$date_separator_idx], $format_string );
   if (sizeof($format_string_array) != 3) {
    return false;
   }

   $date_to_check_array = explode( $separators[$date_separator_idx], $date_to_check );
   if (sizeof($date_to_check_array) != 3) {
    return false;
   }

   $size = sizeof($format_string_array);
   for ($i=0; $i<$size; $i++) {
    if ($format_string_array[$i] == 'mm' || $format_string_array[$i] == 'mmm') $month = $date_to_check_array[$i];
    if ($format_string_array[$i] == 'dd') $day = $date_to_check_array[$i];
    if ( ($format_string_array[$i] == 'yyyy') || ($format_string_array[$i] == 'aaaa') ) $year = $date_to_check_array[$i];
   }
  } else {
   if (strlen($format_string) == 8 || strlen($format_string) == 9) {
    $pos_month = strpos($format_string, 'mmm');
    if ($pos_month != false) {
     $month = substr( $date_to_check, $pos_month, 3 );
     $size = sizeof($month_abbr);
     for ($i=0; $i<$size; $i++) {
      if ($month == $month_abbr[$i]) {
       $month = $i;
       break;
      }
     }
    } else {
     $month = substr($date_to_check, strpos($format_string, 'mm'), 2);
    }
   } else {
    return false;
   }

   $day = substr($date_to_check, strpos($format_string, 'dd'), 2);
   $year = substr($date_to_check, strpos($format_string, 'yyyy'), 4);
  }

  if (strlen($year) != 4) {
   return false;
  }

  if (!settype($year, 'integer') || !settype($month, 'integer') || !settype($day, 'integer')) {
   return false;
  }

  if ($month > 12 || $month < 1) {
   return false;
  }

  if ($day < 1) {
   return false;
  }

  if (zen_is_leap_year($year)) {
   $no_of_days[1] = 29;
  }

  if ($day > $no_of_days[$month - 1]) {
   return false;
  }

  $date_array = array($year, $month, $day);

  return true;
 }


////

with

////
// Check date
function zen_checkdate($date, &$date_string) {
$date = strtolower($date);

if ((defined('MONTH_ABBR'))AND(constant('MONTH_ABBR'))) {$month_abbr = explode(" ", " " . strtolower(MONTH_ABBR));}
else {for ($i=1; $i < 13; $i++) {$month_abbr[$i] = strtolower(strftime("%b",strtotime("$i/1/2004")));}}

for ($i=1; $i < 13; $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 (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 (date("L", strtotime($regs[$y]."0101"))) {$no_of_days = "29";}
else {$no_of_days = "28";};

if ($regs[$d] > $no_of_days) {return false;};

$date_string = $regs[$y] . $regs[$m] . $regs[$d];
return true;
}

////

Hopefully, this is my last modifications of this code, but no promises ;)


PS. For those that are interested; I know there's at least one place in the admin that depends on date() to display the date, but that's not good for internationalisation, because unlike strftime(), date() does not rely on locale. This means that date() will only show english month and day names etc. while strftime() will show localised day and month names. The case I'm aware of at the time, is in admin/includes/header.php on line 153. You may want to replace ```

<?php echo date("r", time()) . 'GMT' . '[' . $_SERVER['REMOTE_ADDR'] . ' ]'; ?>

with something like

<?php echo strftime("%c") . '[' . $_SERVER['REMOTE_ADDR'] . ' ]'; ?>

See [the php manual](http://php.net/manual/en/function.strftime.php) for a list of options.
5 Feb 2005, 12:27 AM
#3
dwno avatar

dwno

Totally Zenned

Join Date:
Jan 2005
Posts:
1,285
Plugin Contributions:
0

Re: International Date Formats

Doh! When I'm about to use this myself for a fresh install, I see there's some line numbers wrong in that second post.

3.
edit includes/functions/functions_general.php (line 403-491)

Those line numbers should be more like 401-507, but your file may be different than mine, so look at the code instead of those line numbers. If you were only replacing what was between line 403-491, I can guarantee you the code would be a little messed up, so don't do that then. ;)

5 Feb 2005, 12:48 AM
#4
dwno avatar

dwno

Totally Zenned

Join Date:
Jan 2005
Posts:
1,285
Plugin Contributions:
0

Re: International Date Formats

.. and don't forget to fix the zen-cart bug related to dates in the advanced search. (fixed in v.1.2.4)

11 Feb 2005, 12:05 AM
#5
sebastiaan avatar

sebastiaan

New Zenner

Join Date:
Jan 2005
Posts:
33
Plugin Contributions:
0

Re: International Date Formats

Hi all,

dwno, i've made the changes as per your post to my english.php file, and it's great for setting up new customers etc. But now my search won't work!!

Has anyone else had this issue?

Not just advanced search either. normal search, or the search from the header bar also.

Any advice gladly recieved!

11 Feb 2005, 12:10 AM
#6
dwno avatar

dwno

Totally Zenned

Join Date:
Jan 2005
Posts:
1,285
Plugin Contributions:
0

Re: International Date Formats

Can't say I've experienced that. What exactly happens? Do you get any error messages?

11 Feb 2005, 11:32 AM
#7
sebastiaan avatar

sebastiaan

New Zenner

Join Date:
Jan 2005
Posts:
33
Plugin Contributions:
0

Re: International Date Formats

hi dwno,
I get:
Fatal error: Only variables can be passed by reference in /home/tsu0010/public_html/includes/modules/pages/advanced_search_result/header_php.php on line 61

If I change header_php.php with the fix for the advanced search by date feature I get exactly the same error (just a different line number........70 or 71 i think).

Bummer!!

Could it be because my English.php is in:

includes/languages/[my template]/english.php
i.e. i am using the overide system for that file? should I be?

Cheers

seb

11 Feb 2005, 2:50 PM
#8
dwno avatar

dwno

Totally Zenned

Join Date:
Jan 2005
Posts:
1,285
Plugin Contributions:
0

Re: International Date Formats

I think you should go over point 2 of my second post here, but don't necessarily trust those line numbers in that post too much, they're supposed to be for guidance only. Instead, you should make sure that you replace the correct code..

Here's the section of includes/modules/pages/advanced_search_result/header_php.php from my file.

  $date_check_error = false;
  if (zen_not_null($dfrom)) {
   if (!zen_checkdate($dfrom, $dfrom_string)) {
    $error = true;
    $date_check_error = true;

    $messageStack->add_session('search', ERROR_INVALID_FROM_DATE);
   }
  }

  if (zen_not_null($dto)) {
   if (!zen_checkdate($dto, $dto_string)) {
    $error = true;
    $date_check_error = true;

    $messageStack->add_session('search', ERROR_INVALID_TO_DATE);
   }
  }

The only differencies from the original are the ones mentioned in point 2 from the second post in this thread.

PS. There's no problem with using template files. :)

12 Feb 2005, 4:41 AM
#9
sebastiaan avatar

sebastiaan

New Zenner

Join Date:
Jan 2005
Posts:
33
Plugin Contributions:
0

Re: International Date Formats

:D Success!

It was the Functions_General.php file. Either i cut & pasted over the wrong code, or just forgot to upload that file from my local server after editing. Either way I started from scratch & now it's all working :-)

Thnaks dwno!

Cheers

Seb

12 Feb 2005, 5:09 AM
#10
ajeh avatar

ajeh

Oba-san

Join Date:
Sep 2003
Location:
Ohio
Posts:
62,757
Plugin Contributions:
1

Re: International Date Formats

Note: advanced_search_result/header_php.php has been fixed in the new v1.2.4 release that is now out ... :)

12 Feb 2005, 10:31 PM
#11
dwno avatar

dwno

Totally Zenned

Join Date:
Jan 2005
Posts:
1,285
Plugin Contributions:
0

Re: International Date Formats

For clarification on ajeh's post:

For my modifications to work, you will still need to edit that file as described in this thread. The only difference is that you don't have to worry about fixing the bug.

For reference, the bug was simply 2 wrongly named variables; $dfrom_to_check and $dto_to_check were being used, but there are no such variables defined. They had to be renamed to $dfrom and $dto, but as already mentioned, this is not an issue for v1.2.4.

PS. And oh yeah.. thanks for the new release! :)

7 Mar 2005, 12:08 PM
#12
gwmbox avatar

gwmbox

New Zenner

Join Date:
Feb 2005
Posts:
38
Plugin Contributions:
0

Re: International Date Formats

Wow - is this really necessary to change the date format - need t go to Aussie format - is there no simply way of doing this - would have thought this as a simple admin feature - but hey if this is the only way then I guess that is what I need ot follow.

Can i ask one question more though what files are required to be edited - the zen_date_raw function is in the language file in admin and non admin - do I change both?

And how do I change the ZC to my local time instead of server time?

Cheers

gwmbox

7 Mar 2005, 8:36 PM
#13
dwno avatar

dwno

Totally Zenned

Join Date:
Jan 2005
Posts:
1,285
Plugin Contributions:
0

Re: International Date Formats

I don't know of any other good ways to get a proper date format.

It shoulf be sufficient to edit only the one in includes/languages/<your language>.php, but you may consider to copy that file to includes/languages/<your template>/<your language>.php and edit that new file instead.

For the server time zone issue, there's a contribution that I believe does what you want.

8 Mar 2005, 12:16 PM
#14
gwmbox avatar

gwmbox

New Zenner

Join Date:
Feb 2005
Posts:
38
Plugin Contributions:
0

Re: International Date Formats

Thanks fo rteh reply, OK I can edit the files OK - but can I use the override function, i.e. for the DOB stuff that edits header_php.php and functions_general.php do I have to edit

Hope I make sense - basically for example instead of editing the file /includes/functions/functions_general.php I want to save it as /includes/function/<templatename>/functions_general.php just as I would edit the templates etc - or can I not do this for functions and modules?

Cheers

Greg

8 Mar 2005, 3:31 PM
#15
dwno avatar

dwno

Totally Zenned

Join Date:
Jan 2005
Posts:
1,285
Plugin Contributions:
0

Re: International Date Formats

Zen Cart doesn't allow overriding of includes/functions/ yet, and the same goes for some of the sub-directories of includes/modules/, like includes/modules/pages/.

The main rule to follow is that wherever there's a directory called 'classic', you can override, otherwise you can't override in most of the cases.

9 Mar 2005, 12:46 PM
#16
gwmbox avatar

gwmbox

New Zenner

Join Date:
Feb 2005
Posts:
38
Plugin Contributions:
0

Re: International Date Formats

Dates in Admin are still being displayed as mm/dd/yyyy instead of dd/mm/yyyy - I am sure I followed everything in this thread - have I not followed something properly or is there something else I need to change?

Cheers

Greg

9 Mar 2005, 7:49 PM
#17
dwno avatar

dwno

Totally Zenned

Join Date:
Jan 2005
Posts:
1,285
Plugin Contributions:
0

Re: International Date Formats

You have probably followed everything correctly as long as the dates in the catalog is working. :) I haven't bothered to look into the admin that much, because I haven't needed it yet. ;)

But, if you mean the date that is displayed in the header of every page in the admin, then I know how do deal with that.. See the PS. in the bottom of the second post in this thread.

18 Mar 2005, 3:24 PM
#18
krazykris avatar

krazykris

New Zenner

Join Date:
Mar 2005
Location:
England
Posts:
23
Plugin Contributions:
0

Re: International Date Formats

Go to the admin area and edit
admin-> configuration-> minimum values-> date of birth
set it to 4.

Replace the old function


when you say replace the old function, which one?

18 Mar 2005, 7:30 PM
#19
dwno avatar

dwno

Totally Zenned

Join Date:
Jan 2005
Posts:
1,285
Plugin Contributions:
0

Re: International Date Formats

Take a peek at the code provided: > function zen_date_raw ;)

That's in includes/languages/<current template>/<your language>.php

25 Mar 2005, 7:01 AM
#20
midez avatar

midez

New Zenner

Join Date:
Dec 2004
Posts:
29
Plugin Contributions:
0

Re: International Date Formats

Maybe i missed something but... When i do the changes as it's said in the first section it works but if i want to look at the date in the admin section it's a totala flipped year. In the form for creating a new account i added, in dob, 1963.09.24 (that's how we write it in sweden). When i then go to the admin section to see the new account it shows me the date like 2037.09.24! Why 2037? What's wrong? Pleeeease!