自定义日期和数字格式字符串(带填充和偏移量)


Custom date and number format string (with padding and offsets)

我尝试根据定义的掩码创建一个可自定义的数字。
这是我制作蒙版的规则

您可以输入任何编号掩码。在这个掩码中,可以使用以下标签:{000000}对应一个数字,该数字将对每个客户递增。

输入与计数器所需长度相同数量的零。

计数器将由左边的零完成,以便有尽可能多的零作为掩码。

{000000+000}与前一个相同,但+符号右侧的数字对应的偏移量从第一个开始应用。

{000000@x}与之前相同,但当达到x月份时(x介于1和12之间),计数器复位为零。

如果使用此选项并且x为2或更高,则还需要序列{yy}{mm}{yyyy}{mm}

{dd} day (01 ~ 31).

{mm}月(01 ~ 12).

{yy}, {yyyy}{y}的年份超过2,4或1个数字。

掩码中的所有其他字符将保持完整。

不允许有空格

创建于2007-03-01的客户示例:
ABC{yy}{mm}-{000000}会给ABC0701-000099
{0000+100}-ZZZ/{dd}/XXX将给予0199-ZZZ/31/XXX

所以我当前的蒙版是C{000000}

 <?php
    $mask = "C{000000}";
$number = 100;
    if (preg_match('/'{(0+)([@'+][0-9]+)?([@'+][0-9]+)?'}/i',$mask,$regType)){
        $masktype=$regType[1];
        $masktype_value=substr(preg_replace('/^TE_/','',$number),0,strlen($regType[1]));//get n first characters of code where n is length in mask
        $masktype_value=str_pad($masktype_value,strlen($regType[1]),"#",STR_PAD_RIGHT);
        $maskwithonlyymcode=$mask;
        $maskwithonlyymcode=preg_replace('/'{(0+)([@'+][0-9]+)?([@'+][0-9]+)?'}/i',$regType[1],$maskwithonlyymcode);
        $maskwithonlyymcode=preg_replace('/'{dd'}/i','dd',$maskwithonlyymcode);
        $maskwithonlyymcode=preg_replace('/'{(c+)(0*)'}/i',$maskrefclient,$maskwithonlyymcode);
        $maskwithonlyymcode=preg_replace('/'{(t+)'}/i',$masktype_value,$maskwithonlyymcode);
        $maskwithnocode=$maskwithonlyymcode;
        $maskwithnocode=preg_replace('/'{yyyy'}/i','yyyy',$maskwithnocode);
        $maskwithnocode=preg_replace('/'{yy'}/i','yy',$maskwithnocode);
        $maskwithnocode=preg_replace('/'{y'}/i','y',$maskwithnocode);
        $maskwithnocode=preg_replace('/'{mm'}/i','mm',$maskwithnocode);
        print "maskwithonlyymcode=".$maskwithonlyymcode." maskwithnocode=".$maskwithnocode."'n<br>";
    }
    ?>

但是它不工作,它正在打印

maskwithonlyymcode=C000000 maskwithnocode=C000000

我想要的输出是C000001 - C000100

这段代码缺少什么?

我不太理解你的代码,所以我无法修复它,但是关于:

<?
function process_mask($mask, $number, $date)
{
    while (preg_match("/'{(.+?)'}/", $mask, $match))
    {
        $outter_code = $match[0];
        $inner_code = $match[1];
        if (preg_match("/^(0+)('+('d+))?$/", $inner_code, $match2))
        {
            $number2 = $number;
            if (!empty($match2[3]))
            {
                $number2 += intval($match2[3]);
            }
            $replacement = str_pad($number2, strlen($match2[1]), "0", STR_PAD_LEFT);
        }
        else
        {
            switch ($inner_code)
            {
                case "dd":
                    $replacement = date("d", $date);
                    break;
                case "mm":
                    $replacement = date("m", $date);
                    break;
                case "y":
                    $replacement = substr(date("Y", $date), 3);
                    break;
                case "yy":
                    $replacement = date("y", $date);
                    break;
                case "yyyy":
                    $replacement = date("Y", $date);
                    break;
                default:
                    trigger_error("Unrecognised code $inner_code");
                    return NULL;
            }
        }
        $mask = str_replace($outter_code, $replacement, $mask);
    }
    return $mask;
}
function test_mask($mask)
{
    $date = mktime(0, 0, 0, 4, 19, 2013);
    echo str_pad($mask, 25)." => ".process_mask($mask, 100, $date)."'n";
}
test_mask("C{000}");
test_mask("C{000000}");
test_mask("C{000000+10}");
test_mask("ABC{yy}{mm}-{000000}");
test_mask("{0000+100}-ZZZ/{dd}/XXX");
?>

输出:

C{000}                    => C100
C{000000}                 => C000100
C{000000+10}              => C000110
ABC{yy}{mm}-{000000}      => ABC1304-000100
{0000+100}-ZZZ/{dd}/XXX   => 0200-ZZZ/19/XXX

我完全不明白你关于重置计数器的规则。您想根据什么日期重置这些数字?当前日期吗?你是否为每个客户保留一些柜台(你没有解释number是什么)?为什么要在某个月份重新设置呢?每隔一段时间重置一次不是更有意义吗?比如每个月(在实现方面,为每个月保留单独的计数器是有意义的,这样格式化逻辑就与当前时间无关了)。一些例子可能有助于理解这一点。

同样对于日期格式,我建议你坚持使用PHP date格式,不要自己发明。

我建议你使用这样的模式(它实际上有点像。net):

{(#[+offset]|php-date-format-string)[:length]}

所以(对于数字= 999和日期= 2013-04-19):

C{#:4}        => C0999
C{#+10:4}     => C1009
C{#:6}        => C000999
C{#:4}/{Y}    => C0999/2013
C{#:4}/{Y:4}  => C0999/2013
C{#:4}/{Y:2}  => C0999/13
C{#:4}/{Y:1}  => C0999/3
C{#:4}/{m}    => C0999/03
C{#:4}/{Y}{m} => C0999/201303
C{#:4}/{Ym}   => C0999/201303

这样的代码会更简单,更可扩展和灵活。