| 1 | <?php |
|---|
| 2 | |
|---|
| 3 | /** |
|---|
| 4 | * Correct wordpress bug. Replaces date_i18n() function which has some bugs. |
|---|
| 5 | */ |
|---|
| 6 | add_filter('date_i18n', 'fix_date_i18n', 10, 4); |
|---|
| 7 | function fix_date_i18n($dateformated, $dateformatstring, $unixtimestamp = false, $gmt = false) |
|---|
| 8 | { |
|---|
| 9 | /* @var $wp_locale WP_Locale */ |
|---|
| 10 | global $wp_locale; |
|---|
| 11 | $timestamp = $unixtimestamp; |
|---|
| 12 | |
|---|
| 13 | // get current timestamp if $unixtimestamp is false |
|---|
| 14 | if (false === $timestamp) |
|---|
| 15 | { |
|---|
| 16 | if ($gmt) |
|---|
| 17 | $timestamp = time(); |
|---|
| 18 | else |
|---|
| 19 | $timestamp = current_time('timestamp'); |
|---|
| 20 | } |
|---|
| 21 | |
|---|
| 22 | |
|---|
| 23 | // get components of the date (timestamp) as array |
|---|
| 24 | $datecomponents = getdate($timestamp); |
|---|
| 25 | |
|---|
| 26 | // numeric representation of a month, with leading zeros |
|---|
| 27 | $datemonth = $wp_locale->get_month($datecomponents['mon']); |
|---|
| 28 | $datemonth_abbrev = $wp_locale->get_month_abbrev($datemonth); |
|---|
| 29 | // numeric representation of the day of the week |
|---|
| 30 | $dateweekday = $wp_locale->get_weekday($datecomponents['wday']); |
|---|
| 31 | $dateweekday_abbrev = $wp_locale->get_weekday_abbrev($dateweekday); |
|---|
| 32 | // get if hour is Ante meridiem or Post meridiem |
|---|
| 33 | $meridiem = $datecomponents['hours'] >= 12 ? 'pm' : 'am'; |
|---|
| 34 | // lowercase Ante meridiem and Post meridiem hours |
|---|
| 35 | $datemeridiem = $wp_locale->get_meridiem($meridiem); |
|---|
| 36 | // uppercase Ante meridiem and Post meridiem |
|---|
| 37 | $datemeridiem_capital = $wp_locale->get_meridiem(strtoupper($meridiem)); |
|---|
| 38 | |
|---|
| 39 | // escape literals |
|---|
| 40 | $dateweekday_abbrev = backslashit($dateweekday_abbrev); |
|---|
| 41 | $datemonth = backslashit($datemonth); |
|---|
| 42 | $dateweekday = backslashit($dateweekday); |
|---|
| 43 | $datemonth_abbrev = backslashit($datemonth_abbrev); |
|---|
| 44 | $datemeridiem = backslashit($datemeridiem); |
|---|
| 45 | $datemeridiem_capital = backslashit($datemeridiem_capital); |
|---|
| 46 | |
|---|
| 47 | // the translated format string |
|---|
| 48 | $translateddateformatstring = ''; |
|---|
| 49 | // the 2 arrays map a format literal to its translation (e. g. 'F' to the escaped month translation) |
|---|
| 50 | $tranlateformates = array('D', 'F', 'l', 'M', 'a', 'A', 'c', 'r'); |
|---|
| 51 | $translations = array( |
|---|
| 52 | $dateweekday_abbrev, // D |
|---|
| 53 | $datemonth, // F |
|---|
| 54 | $dateweekday, // l |
|---|
| 55 | $datemonth_abbrev, // M |
|---|
| 56 | $datemeridiem, // a |
|---|
| 57 | $datemeridiem_capital, // A |
|---|
| 58 | 'Y-m-d\TH:i:sP', // c |
|---|
| 59 | sprintf('%s, d %s Y H:i:s O', $dateweekday_abbrev, $datemonth_abbrev), // r |
|---|
| 60 | ); |
|---|
| 61 | |
|---|
| 62 | // find each format literal that needs translation and replace it by its translation |
|---|
| 63 | // respects the escaping |
|---|
| 64 | // iterate $dateformatstring from ending to beginning |
|---|
| 65 | for ($i = strlen($dateformatstring) - 1; $i > -1; $i--) |
|---|
| 66 | { |
|---|
| 67 | // test if current char is format literal that needs translation |
|---|
| 68 | $tranlateformateindex = array_search($dateformatstring[$i], $tranlateformates); |
|---|
| 69 | |
|---|
| 70 | if ($tranlateformateindex !== false) |
|---|
| 71 | { |
|---|
| 72 | // counts the slashes (the escape char) in front of the current char |
|---|
| 73 | $slashescounter = 0; |
|---|
| 74 | |
|---|
| 75 | // count all slashes left-hand side of the current char |
|---|
| 76 | for ($j = $i - 1; $j > -1; $j--) |
|---|
| 77 | { |
|---|
| 78 | if ($dateformatstring[$j] == '\\') |
|---|
| 79 | $slashescounter++; |
|---|
| 80 | else |
|---|
| 81 | break; |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | // number of slashes is even |
|---|
| 85 | if ($slashescounter % 2 == 0) |
|---|
| 86 | // current char is not escaped, therefore it is a format literal |
|---|
| 87 | $translateddateformatstring = $translations[$tranlateformateindex] . $translateddateformatstring; |
|---|
| 88 | else |
|---|
| 89 | // current char is escaped, therefore it is not a format literal, just add it unchanged |
|---|
| 90 | $translateddateformatstring = $dateformatstring[$i] . $translateddateformatstring; |
|---|
| 91 | } |
|---|
| 92 | else |
|---|
| 93 | // current char is no a format literal, just add it unchanged |
|---|
| 94 | $translateddateformatstring = $dateformatstring[$i] . $translateddateformatstring; |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | $dateformatstring = $translateddateformatstring; |
|---|
| 98 | |
|---|
| 99 | if ($gmt) |
|---|
| 100 | // get GMT date string |
|---|
| 101 | $dateformated = gmdate($dateformatstring, $timestamp); |
|---|
| 102 | else |
|---|
| 103 | { |
|---|
| 104 | // get Wordpress time zone |
|---|
| 105 | $timezone_string = get_option('timezone_string'); |
|---|
| 106 | |
|---|
| 107 | // TODO: If get_option('timezone_string') is empty we should work with the gmt offset. Not easy to implement. |
|---|
| 108 | /*// get Wordpress gmt offset (in hours) |
|---|
| 109 | $gmtoffset = get_option('gmt_offset'); |
|---|
| 110 | |
|---|
| 111 | // try to get time zone from gmt offset if timezone_string is not given |
|---|
| 112 | if($timezone_string == '' && $gmtoffset !== false) |
|---|
| 113 | { |
|---|
| 114 | $timezone_string = timezone_name_from_abbr('', intval($gmtoffset) * HOUR_IN_SECONDS, 0); |
|---|
| 115 | }*/ |
|---|
| 116 | |
|---|
| 117 | if ($timezone_string) |
|---|
| 118 | { |
|---|
| 119 | // create time zone object |
|---|
| 120 | $timezone_object = timezone_open($timezone_string); |
|---|
| 121 | // create date object from time zone object |
|---|
| 122 | $localdateobject = date_create(null, $timezone_object); |
|---|
| 123 | // set time and date of $localdateobject to $timestamp |
|---|
| 124 | $datecomponents = isset($datecomponents) ? $datecomponents : getdate($timestamp); |
|---|
| 125 | date_date_set($localdateobject, $datecomponents['year'], $datecomponents['mon'], $datecomponents['mday']); |
|---|
| 126 | date_time_set($localdateobject, $datecomponents['hours'], $datecomponents['minutes'], $datecomponents['seconds']); |
|---|
| 127 | // format date according to the Wordpress time zone |
|---|
| 128 | $dateformated = date_format($localdateobject, $dateformatstring); |
|---|
| 129 | } |
|---|
| 130 | else |
|---|
| 131 | { |
|---|
| 132 | // fall back if no Wordpress time zone set |
|---|
| 133 | $dateformated = date($dateformatstring, $i); |
|---|
| 134 | } |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | return $dateformated; |
|---|
| 138 | } |
|---|