坚持尝试将输入转换为某种格式的字符串

时间:2012-07-12 19:29:30

标签: php

所以我在db中有一个字段用于传递时间,并且它具有某种格式(不是我的设计肯定!): 以下是几个例子:

M,T,W,TH; MTWTH 9至4关闭12比1

T,W,TH,F; TTHF 9至5关闭12至2,W 9至12

T,W,TH,F; T 10至7结束2至3,WTH 9至6结束1至2,F 8至5结束1至2

所以基本上,你有一个天数列表,用逗号分隔,然后是分号。 在分号后,有一个天数列表,没有分开,然后是交货时间,包括休息时间。 问题是,每天的交货时间可能不同,所有日子都相同,或者说周一和周二相同,周三不同,周四和周五相同(但周四和周五交货时间不同于周一和周一)星期二)。 如果交货时间与某些天相匹配,那么这些日子应该组合在一起,交货时间列在小组日之后,然后列出其他匹配或单日。指定交货时间的第一天必须先行。

我知道,格式是荒谬的,交付日期/时间应该在按组织ID链接的单独表中,但它是他们现在用于某些下载文件的格式。 我希望稍后改变它,但现在...... 我无法弄清楚如何将输入从4个下拉列表(From,To,Closed From,Closed To)转换为该格式。 任何一天都可能没有关闭时间。至少有一天必须指定交货时间(我检查一下)。

我当然得到了第一部分(在分号前) - 这很容易,之后我完全陷入困境。 如果交货的所有日子都有相同的时间,我就不会有问题。但由于它每天都可能完全不同,我不知道该怎么做。

所以到目前为止这是处理块:

$ trimmed是已修剪的POST值数组,

$ trimmed ['1Monday']是星期一从,$ trimmed ['2Monday']是星期一到,

$ trimmed ['3Monday']是周一关闭的,$ trimmed ['4Monday']是周一关闭。

因此$ M_times变量将具有周一的开/关时间。

$ days_del数组用于稍后创建一个字符串,该字符串是所需格式的第一部分。

我可以在指定的某些时间获得第一天,之后我可以尝试捕获任何匹配,但如果第一个交付日与其他日期的值不同,那么这是没有用的,但之后会有一些匹配的值。我甚至不确定我是否需要使用ano((编号)天数组,或者我只能使用带有M-F键的主数据。

<?php

$days = array('M' => 'Monday', 'T' => 'Tuesday', 'W' => 'Wednesday', 'TH' => 'Thursday', 'F' => 'Friday');

$days_numbered = array(1 => 'M', 'T', 'W', 'TH', 'F');

$days_del = $matches = $full_list = array();

$days_delivery2 = '';

$count_no_del = 0;  # initialize count for days with no delivery
$times_6 = '';



foreach ($days as $k => $v){  #####  Beginning of days loop


if (isset($trimmed["1$v"]) &&  isset($trimmed["2$v"])){ #  If both closing and opening times have been specified

$days_del[] = $k;
${$k.'_times'} = $trimmed["1$v"] . ' TO ' . $trimmed["2$v"];

if ((!isset($trimmed["3$v"]) && isset($trimmed["4$v"])) || (isset($trimmed["3$v"]) && !isset($trimmed["4$v"]))){  #  If only beginning or only end of lunch(?) break has been specified

$errors[] = 'Delivery times for $v - please specify both start and end of closing time.';

}elseif (isset($trimmed["3$v"]) && isset($trimmed["4$v"]){  #  If both beginning and end of lunch(?) breakh have been specified

${$k.'_times'} .= 'CLOSED' .  $trimmed["3$v"] . ' TO ' . $trimmed["4$v"];
}

    }elseif ((!isset($trimmed["1$v"]) &&  isset($trimmed["2$v"])) || (isset($trimmed["1$v"]) &&  !isset($trimmed["2$v"]))){  #  If only closing or only  opening time has been specified

$errors[] = 'Delivery times for $v - please specify both start and end of delivery time.';
${$k.'_times'} = NULL;

    }elseif (!isset($trimmed["1$v"]) &&  !isset($trimmed["2$v"])){  # No delivery times specified for this day

${$k.'_times'} = NULL;
$count_no_del++;

    }

$full_list["$k"] = ${$k.'_times'};

}  #####  End of days loop



if ($count_no_del > 0){  #  If there are no delivery days specified
$errors[] = 'You must specify delivery hours for at least one day of the week.';
}

$days_delivery1 = implode(',', $days_del);
$days_delivery1 = $days_delivery1 . ' ; ';



foreach ($days_numbered as $num => $val){  #  Getting first day for which delivery hours have been specified
if (isset(${$val.'_times'}) && (${$val.'_times'} != NULL)){
${'times_'.$num} = ${$val.'_times'};
$first_day = $num;
break;
}
}




$check_array = array_keys($full_list, ${'times_'.$first_day}));  #  checking how many other days match the delivery hours for the first specified day.

foreach ($check_array as $array_key){
$days_delivery2 .= $array_key;
}

$days_delivery2 .= " " . ${'times_'.$first_day};


$note_line = $days_delivery1 . " "  ; #  second part, something like 'MTH 9 To 5, TW 10 TO 5 CLOSED 1 TO 2, F 10 TO 2' should go a s the second part of the string.
?>

正如你所看到的,在以该格式获取字符串的第一部分($ days_delivery1)后,我陷入困境,不知道我到底在做什么。我有一个想法,即使用2个不同的数组(主要的一个和编号的数组)并使用array_keys来查找匹配的值,但是每当我尝试使用它时,我就会碰到一堵墙。任何想法都会被贬低。

1 个答案:

答案 0 :(得分:3)

这里可能很困难的事情是将第二部分的条目分组。为了克服这个问题,我建议你将时间转换为4位数表示来规范化它们并连接模式,因此为每个模式创建一个“签名”。

在下面的示例中,我将讨论以下$_POST数组将导致相应结果字符串的主体:

 $_POST1 = array(
   '1Monday' => 9,
   '2Monday' => 5,
   '3Monday' => 12,
   '4Monday' => 1,
   '1Tuesday' => 9,
   '2Tuesday' => 5,
   '3Tuesday' => 12,
   '4Tuesday' => 1,
   '1Wednesday' => 9,
   '2Wednesday' => 5,
   '3Wednesday' => 12,
   '4Wednesday' => 1,
   '1Thursday' => 9,
   '2Thursday' => 5,
   '3Thursday' => 12,
   '4Thursday' => 1,
   '1Friday' => 9,
   '2Friday' => 4,
   '3Friday' => 11,
   '4Friday' => 12
 );
 $result1 = "M, T, W, TH, F ; MTWTH 9 TO 5 CLOSED 12 TO 1, F 9 TO 4 CLOSED 11 TO 12";     

 $_POST2 = array(
   '1Monday' => '',
   '2Monday' => '',
   '3Monday' => '',
   '4Monday' => '',
   '1Tuesday' => 9,
   '2Tuesday' => 5,
   '3Tuesday' => 12,
   '4Tuesday' => 1,
   '1Wednesday' => 9,
   '2Wednesday' => 5,
   '3Wednesday' => 12,
   '4Wednesday' => 1,
   '1Thursday' => 9,
   '2Thursday' => 5,
   '3Thursday' => 12,
   '4Thursday' => 1,
   '1Friday' => 9,
   '2Friday' => 5,
   '3Friday' => 12,
   '4Friday' => 1
 );
 $result2 = "T, W, TH, F ; TWTHF 9 TO 5 CLOSED 12 TO 1";

现在让我们来看看我们如何处理这些数据。我将假设我们正在直接使用未处理的POST数组。

<?php

  // Obviously we will need this map if the inputs use the full day names
  $days = array('M' => 'Monday', 'T' => 'Tuesday', 'W' => 'Wednesday', 'TH' => 'Thursday', 'F' => 'Friday');

  // A couple of arrays to hold the results of the loop iterations
  $resultDays = $resultTimes = array();

  // First we iterate over the days
  foreach ($days as $dayCode => $dayFull) {

    // Data about this day
    $dayData = array(
      'open' => 0,
      'close' => 0,
      'lunchClose' => 0,
      'lunchOpen' => 0,
      'days' => array()
    );

    // First get the open/close times
    $open = $_POST["1$dayFull"];
    $close = $_POST["2$dayFull"];
    if (empty($open) || empty($close)) {
      // If we don't have both open/close times, skip this day
      continue;
    }

    // We definitely open on this day
    $resultDays[] = $dayCode;
    $dayData['open'] = $open;
    $dayData['close'] = $close;

    // Pad the strings to make the signature
    $openPadded = str_pad($open, 2, "0", STR_PAD_LEFT);
    $closePadded = str_pad($close, 2, "0", STR_PAD_LEFT);

    // Now look at lunch times
    $lunchClose = $_POST["3$dayFull"];
    $lunchOpen = $_POST["4$dayFull"];
    if (!empty($lunchClose) || !empty($lunchOpen)) {
      // If we have both open/close times, add a lunch break

      // Add data to $dayData
      $dayData['lunchClose'] = $lunchClose;
      $dayData['lunchOpen'] = $lunchOpen;

      // Pad the strings to make the signature
      $lunchClosePadded = str_pad($lunchClose, 2, "0", STR_PAD_LEFT);
      $lunchOpenPadded = str_pad($lunchOpen, 2, "0", STR_PAD_LEFT);

    } else {
      // So we don't break this signature
      $lunchClosePadded = $lunchOpenPadded = '';
    }

    // Build the signature
    $signature = $openPadded.$closePadded.$lunchClosePadded.$lunchOpenPadded;

    // Add day data to result times array
    if (!isset($resultTimes[$signature])) {
      $resultTimes[$signature] = $dayData;
    }
    $resultTimes[$signature]['days'][] = $dayCode;

  }

  // Now we can build the string

  // Like you say, first part is easy
  $firstPart = implode(', ', $resultDays);

  // Loop $resultTimes and construct to more sensible arrangements
  $secondPart = array();
  foreach ($resultTimes as $block) {
    $str = implode('', $block['days'])." {$block['open']} TO {$block['close']}";
    if (!empty($block['lunchClose']) && !empty($block['lunchOpen'])) {
      $str .= " CLOSED {$block['lunchClose']} TO {$block['lunchOpen']}";
    }
    $secondPart[] = $str;
  }

  // Now we can construct the final string
  $finalResult = $firstPart." ; ".implode(', ', $secondPart);

See working

嗯,这很有趣。