Числа прописью с рублями, минутами и метрами

Краткое описание алгоритмов date-diff, очень просто!

Propis::get("919.12") => девятьсот девятнадцать рублей 12 копеек;

Propis::get("1071.11") => одна тысяча семьдесят один рубль 11 копеек;

Propis::get("9.11.2") => девять часов одиннадцать минут две секунды;

Propis::get("1002000219.02") => один миллиард два миллиона двести девятнадцать рублей 02 копейки;

Propis::get("23:14:09") => двадцать три часа четырнадцать минут девять секунд;

Propis::get("2-3-00 12:00:54") => два года три месяца 0 дней двенадцать часов 0 минут пятьдесят четыре секунды;

Propis::get_one(2354547758301125, array("миллиметр", "миллиметра", "миллиметров")) => 2 354 пятьсот сорок семь миллиардов семьсот пятьдесят восемь миллионов триста одна тысяча сто двадцать пять миллиметров;

Propis::get(n_time_diff ("2013-01-01 00:00:00")) => В Иркутске до Нового Года осталось: 0 часов 0 минут 0 секунд;

Исходный код:

<?php
//////////////////////////
include 'header1.php'; //это для строк с примерами. 
//При использовании скрипта в другом месте убрать!!

class Propis 
{
    private static 
$def = array (
        
'forms' => array(2, 0, 1, 1, 1, 2, 2, 2, 2, 2),
        
        
'words' => array(
            
0 => array('секунда', 'секунды', 'секунд'),
            
1 => array('минута', 'минуты', 'минут'),
            
2 => array('час', 'часа', 'часов'),
            
3 => array('день', 'дня', 'дней'),
            
4 => array('месяц', 'месяца', 'месяцев'),
            
5 => array('год', 'года', 'лет'),
            
'r' => array('рубль', 'рубля', 'рублей'),
            
'k' => array('копейка', 'копейки', 'копеек'),
        ),
        
        
'rank' => array(
            
0 => array('штука', 'штуки', 'штук'),
            
1 => array('тысяча', 'тысячи', 'тысяч'),
            
2 => array('миллион', 'миллиона', 'миллионов'),
            
3 => array('миллиард', 'миллиарда', 'миллиардов'),
        ),
    
        
'nums' => array(
            
'0' => array( '', 'десять', '', ''),
            
'1' => array( 'один', 'одиннадцать', '', 'сто'),
            
'2' => array( 'два', 'двенадцать', 'двадцать', 'двести'),
            
'1f' => array( 'одна', '', '', ''),
            
'2f' => array( 'две', '', '', ''),
            
'3' => array( 'три', 'тринадцать', 'тридцать', 'триста'),
            
'4' => array( 'четыре', 'четырнадцать', 'сорок', 'четыреста'),
            
'5' => array( 'пять', 'пятнадцать', 'пятьдесят', 'пятьсот'),
            
'6' => array( 'шесть', 'шестнадцать', 'шестьдесят', 'шестьсот'),
            
'7' => array( 'семь', 'семнадцать', 'семьдесят', 'семьсот'),
            
'8' => array( 'восемь', 'восемнадцать', 'восемьдесят', 'восемьсот'),
            
'9' => array( 'девять', 'девятнадцать', 'девяносто', 'девятьсот')
        )
    );
    
    public static function 
get($str) 
    {
        
$def =& self::$def;
        
$res = array();
        
$group = preg_split("/\D+/", $str);
        
        if (
count($group) < 3) //деньги
        
{
            
$res[] = self::get_one($group[0], $def['words']['r']);
            
$def['rank'][0] = $def['words']['k'];
            
$res[] = self::num2word($group[1]);
        }
        else 
//время - дата
        
{
            
$group = array_reverse($group);    
            foreach (
$group as $key => $value) 
            {
                if (
trim($value)) 
                {
                    
$def['rank'][0] = $def['words'][$key];
                    
$res[] = self::num2word($value, 0);
                }
            }
            
$res = array_reverse($res);
        }
        return 
implode(' ', $res);
    }
    
    public static function 
get_one($num, $words = array()) 
    {
        if (
count($words)) self::$def['rank'][0] = $words;
        
$str = number_format($num, 0, '', ',');
        
        
$r = explode(',', $str);
        
$r = array_reverse($r);
        
$word = array();
        
        foreach(
$r as $key => $value) 
        {
            
$word[] = self::num2word($value, $key);
        }
        
        
$word = array_reverse($word);
        return 
implode(' ', $word);
    }
    
    private static function 
num2word($str, $key = null) 
    {
        if (
intval(trim($str)) === 0 && $key !== 0) return '';
        
$def = self::$def;
        
$nums = $def['nums'];
        
$forms = $def['forms'];
        
$rank = $def['rank'];

        
$dig = str_split(sprintf('%02d', $str));
        
$dig = array_reverse($dig);
        
//если нет ключа, вернуть цифры с правильной plural-формой (можно использовать для копеек)
        
if (!isset($key)) return $str . ' ' . ((1 == $dig[1]) ? $rank[0][2] : $rank[0][$forms[$dig[0]]]);
        
//если кончился запас "миллионов", вернуть цифры
        
if (!isset($rank[$key])) return $str;
        
$rank = $rank[$key];
        
        
$f = (preg_match("/[ая]$/", $rank[0]) && ($dig[0] == 1 || $dig[0] == 2)) ? 'f' : '';
        
        if (
1 == $dig[1]) 
        {
            
$num_word = $nums[$dig[0]][1];
            
$word = $rank[2];
        }
        else 
        {
            
$num_word = $nums[$dig[1]][2] . ' ' . $nums[$dig[0] . $f][0];
            
$word = $rank[$forms[$dig[0]]];
        }
        
        
$sotni = (isset($dig[2])) ? $nums[$dig[2]][3] . ' ' : '';
        if (!
trim($num_word)) $num_word = '0'; //это для секунд (рубли сюда не доходят)
        
return $sotni . $num_word . ' ' . $word;
    }
    
}

//Бонус: "нативный" time_diff()

function n_time_diff ($d1, $d2 = null)
{
    if (empty(
$d2)) $d2 = date('Y-m-d H:i:s');
    
$time2 = strtotime($d2);
    
$time = (strtotime($d1) - $time2);
    
    if (
$time < 0) return '00:00:00';
    
$Y = gmdate('Y', $time) - gmdate('Y', 0);
    
$m = gmdate('m', $time) - gmdate('m', 0);
    
$d = gmdate('d', $time) - gmdate('d', 0);
    
$h = gmdate('H:i:s', $time);
    
    
$curr_m = date('m', $time2) - 1;
    
$delta_m = array(1, -2, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, -2, 1, 0);
    
$days_0 = array_slice($delta_m, 0, $m);
    
$days_real = array_slice($delta_m, $curr_m, $m);
    
$days_corr = array_sum($days_real) - array_sum($days_0);
    
    
$d -= $days_corr;
    if (
$d < 0) {
        
$d = 30 - $delta_m[$curr_m] + $d;
        
$m -= 1;
    }
    if (
$m < 0) {
        
$m = 11;
        
$Y -= 1;
    }
    
    return 
"$Y-$m-$d $h";
}

//это для вывода на экран php-кода // 
print '<h3>Исходный код:</h3>'; ////
highlight_file(__FILE__); /////////
//При использовании скрипта в другом месте убрать!!