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

Php 自定义日期和数字格式字符串(带填充和偏移),php,preg-match,string-formatting,Php,Preg Match,String Formatting,我试图根据定义的掩码创建一个可自定义的数字。 这是我做面具的规则 您可以输入任何编号掩码。在此掩码中,可以使用以下标记:{000000}对应于一个数字,该数字将在每个客户上递增 输入所需计数器长度的尽可能多的零 计数器将由左边的零完成,以便有与掩码一样多的零 {000000+000}与前面相同,但从第一个开始应用与+符号右侧数字对应的偏移量 {000000@x}与上一个相同,但当达到月份x时(x介于1和12之间),计数器将重置为零 如果使用此选项且x为2或更高,则还需要序列{yy}{mm}或{y

我试图根据定义的掩码创建一个可自定义的数字。
这是我做面具的规则

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

输入所需计数器长度的尽可能多的零

计数器将由左边的零完成,以便有与掩码一样多的零

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

{000000@x}
与上一个相同,但当达到月份
x
时(
x
介于1和12之间),计数器将重置为零

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

{dd}
天(01至31)

{mm}
月份(01至12)

{yy}
{yyy}
{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>";

    }

    ?>
我想要的输出是
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");

?>
我绝对不理解你关于重置计数器的规则。您希望根据什么日期重置数字?当前日期?您是否为每位客户保留了一些柜台(您没有解释
号码是什么)?为什么要在某个月重新设置它?如果每隔一段时间重新设置,不是更有意义吗?就像每个月一样(从实现的角度来看,每个月保留单独的计数器是有意义的,这样格式化逻辑与当前时间无关)。一些例子可能有助于理解这一点

此外,对于日期格式,我建议您坚持使用PHP
date
格式,不要发明自己的格式

我建议您使用这样的模式(实际上有点像.NET):

{(#[+offset]| php日期格式字符串)[:length]}
So(编号为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

这方面的代码将更加简单、可扩展和灵活。

我的上帝!!!!过度杀戮regex@itachi这就是我们所说的Mangekyu正则表达式:p@Apptester我明白了。。。但是你给我们展示了一个没有合理输入数据的残忍的过度杀伤力的解决方案。这让我的大脑受伤了。。。你能解释一下你到底想做什么吗。。您将要讨论一些非常复杂的问题,这可能是一个非常简单的解决方案。这要好得多,请您再添加3-5个文字示例,说明代码的实际外观?因为我仍然不确定
{}
是文字还是仅仅封装了一个组。我已经用替代格式的建议更新了我的答案
<?

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");

?>