WordPress.org

Make WordPress Core

Ticket #25768: core-fixes.php

File core-fixes.php, 5.0 KB (added by raubvogel, 6 years ago)

Fixes date_i18n() by filtering (no core modification).

Line 
1<?php
2
3/**
4 * Correct wordpress bug. Replaces date_i18n() function which has some bugs.
5 */
6add_filter('date_i18n', 'fix_date_i18n', 10, 4);
7function 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}