5

I have some code (it's part of a wordpress plugin) which takes a text string, and the format specifier given to date(), and attempts to parse it into an array containing hour, minute, second, day, month, year.

Currently, I use the following code (note that strtotime is horribly unreliable with things like 01/02/03)

// $format contains the string originally given to date(), and $content is the rendered string
if (function_exists('date_parse_from_format')) {
    $content_parsed = date_parse_from_format($format, $content);
} else {
    $content = preg_replace("([0-9]st|nd|rd|th)","\\1",$content);
    $content_parsed = strptime($content, dateFormatToStrftime($format));
    $content_parsed['hour']=$content_parsed['tm_hour'];
    $content_parsed['minute']=$content_parsed['tm_min'];
    $content_parsed['day']=$content_parsed['tm_mday'];
    $content_parsed['month']=$content_parsed['tm_mon'] + 1;
    $content_parsed['year']=$content_parsed['tm_year'] + 1900;
}

This actually works fairly well, and seems to handle every combination I've thrown at it.

However, recently someone gave me 24 Ноябрь, 2010. This is Russian for November 24, 2010 [the date format was j F, Y], and it is parsed as year = 2010, month = null, day = 24.

Are there any functions that I can use that know how to translate both November and Ноябрь into 11?

EDIT:

Running print_r(setlocale(LC_ALL, 0)); returns C. Switching back to strptime() seems to fix the problem, but the docs warn:

Internally, this function calls the strptime() function provided by the system's C library. This function can exhibit noticeably different behaviour across different operating systems. The use of date_parse_from_format(), which does not suffer from these issues, is recommended on PHP 5.3.0 and later.

Is date_parse_from_format() the correct API, and if so, how do I get it to recognize the language?

hakre
  • 193,403
  • 52
  • 435
  • 836
Mikeage
  • 6,424
  • 4
  • 36
  • 54

3 Answers3

3

Try to set the locale to Russian as hinted in the manual:

Month and weekday names and other language dependent strings respect the current locale set with setlocale() (LC_TIME).

Gordon
  • 312,688
  • 75
  • 539
  • 559
  • the problem is that it's a plugin that others might use... it would be nice to find a "proper" solution. But I think I'd just stick to `strptime()` until I find a case when it's not working... – Mikeage Jan 13 '11 at 07:12
  • @Mikeage A UnitTest is proper :) You can try if `date_create_from_format` can parse localized strings. I dont think it does, but give it a try nonetheless. – Gordon Jan 13 '11 at 07:56
  • I tried both strptime() and date_create_from_format to parse an italian date, like 18 Mag 2013 (= 2013-05-18) with no success. – damko May 03 '13 at 22:43
  • 1
    @dam try the solutions offered here: http://stackoverflow.com/questions/113829/how-to-convert-date-to-timestamp-in-php/6028533#6028533 – Gordon May 04 '13 at 06:14
  • @Gordon I had a chance to try but nope, I couldn't find any way to transform from Italian to English using IntlDateFormatter. It is possible from English to Italian though. Basically using IntlDateFormatter: - from "2014-09-12" you can have "Set 12 2014" or "12 Set 2014" (these are Italian) - from "Set 12 2014" or "12 Set 2014" you can't get to "2014-09-12". You need to translate "Set" to "Sep" first – damko Sep 12 '14 at 21:29
1

you could try take a locale parameter and call locale_set_default($locale) before doing the date parsing.

$originalLocale = locale_get_default();
$locale ? $locale : $originalLocale;
locale_set_default(locale);

// date parsing code

locale_set_default($originalLocale);

I haven't testing this but it's work a try. FYI, I believe the locale string for Russian is "ru-Latn"

xzyfer
  • 13,937
  • 5
  • 35
  • 46
  • My problem is that I don't know what the locale is supposed to be, and I assume it's set already – Mikeage Jan 11 '11 at 10:03
0

I see that the question is already answered but none of the solutions provided worked for me.

This is my solution:

if(!preg_match('/^en_US/', $locale)){

    $months_short = array('jan' => t('jan'), 'feb' => t('feb'), 'mar' => t('mar'), 'apr' => t('apr'),
            'may' => t('may'), 'jun' => t('giu'), 'jul' => t('lug'), 'aug' => t('ago'),
            'sep' => t('set'), 'oct' => t('ott'), 'nov' => t('nov'), 'dec' => t('dec'));

    foreach ($months_short as $month_short => $month_short_translated) {
        $date = preg_replace('/'.$month_short_translated.'/', $month_short, strtolower($date));
    }

}

$pieces = date_parse_from_format($format,$date);

if($pieces && $pieces['error_count'] == 0 && checkdate($pieces['month'], $pieces['day'], $pieces['year'])){

    return date('Y-m-d', mktime(0,0,0,$pieces['month'],$pieces['day'],$pieces['year'])); 

}

Where t() returns the translated abbreviation for the month.

Probably not the best solution ever (because it fails if there is no valid translation) but it works for my case.

damko
  • 301
  • 1
  • 12