【问题标题】:Separate a long string of Dates and Times分隔一长串日期和时间
【发布时间】:2019-06-07 12:58:23
【问题描述】:

我在 PHP 中有以下字符串:

$date_range_create_event = "Jan 12, 2019 08:00 PM - Feb 14, 2019 06:00 AM";

我想将它分成 4 个部分,然后能够将它们作为变量访问:

  • 开始日期(2019 年 1 月 12 日)
  • 开始时间(08:00 PM)
  • 结束日期(2019 年 2 月 14 日)
  • 结束时间(06:00 AM)

我想让这个动态。有什么我可以通过代码自动分离的吗?

编辑:

这是我尝试提取的开始日期:

$start_date = substr($date_range_create_event, 0, strpos($date_range_create_event, ' ', strpos($date_range_create_event, ' ')+1));

【问题讨论】:

  • 你有没有尝试过?
  • 是的,但不幸的是我想不出一个匹配我需要的所有东西的模式

标签: php regex str-replace


【解决方案1】:

如果您只想将字符串拆分为四个部分,那么您可以在一个 preg_ 调用中执行此操作,以分解两个分隔符。

代码:(Demo)

$date_range_create_event = "Feb 13, 2019 03:00 PM - Mar 1, 2019 11:00 PM";

$parts = preg_split ("/ - | (?=\d\d:)/", $date_range_create_event);
var_export($parts);

输出:

array (
  0 => 'Feb 13, 2019',
  1 => '03:00 PM',
  2 => 'Mar 1, 2019',
  3 => '11:00 PM',
)

由此,您可以使用list() 或php7+“数组解构”将值分配给变量。

模式说,每次遇到都分裂:

  1. 空格、连字符、空格或
  2. 一个空格(后跟 2 小时数字,然后是一个冒号) 使用 (?=...) 前瞻,以便时间子字符串不会“消耗”为进程中分隔子字符串的一部分。

【讨论】:

    【解决方案2】:

    我们可以尝试使用正则表达式拆分和匹配的组合:

    $input = "Jan 12, 2019 08:00 PM - Feb 14, 2019 06:00 AM"; 
    $parts = preg_split ("/\s+-\s+/", $input);
    foreach($parts as $date) {
        if (preg_match("/([a-z]{3} \d{1,2}, \d{4}) (\d{2}:\d{2} (?:AM|PM))/i", $date, $results)) {
            echo "date: " . $results[1] . "\n";
            echo "time: " . $results[2] . "\n";
        }
    }
    
    date: Jan 12, 2019
    time: 08:00 PM
    date: Feb 14, 2019
    time: 06:00 AM
    

    【讨论】:

    • OP 不懂正则表达式,盲目地复制粘贴了你的 sn-p,当 day 是单个整数时,这个 sn-p 会导致后续问题。也许你可以解释一下。正则表达式。为什么要使用preg_split()——对我来说似乎有点矫枉过正,因为没有可变性。
    【解决方案3】:

    您可以从字符串的每个拆分部分(围绕-)创建一个DateTime 对象,然后以您需要的任何格式从结果对象中输出您需要的任何日期/时间片段:

    $date_range_create_event = "Jan 12, 2019 08:00 PM - Feb 14, 2019 06:00 AM";
    list($start, $end) = array_map(function ($d) { return new DateTime($d); }, explode('-', $date_range_create_event));
    echo "Start date = " . $start->format('M j, Y') . "\n";
    echo "Start date = " . $start->format('Y-m-d') . "\n";
    echo "Start time = " . $start->format('h:i A') . "\n";
    echo "Start time = " . $start->format('H:i') . "\n";
    echo "End date = " . $end->format('M j, Y') . "\n";
    echo "End time = " . $end->format('h:i A') . "\n";
    

    输出:

    Start date = Jan 12, 2019 
    Start date = 2019-01-12 
    Start time = 08:00 PM 
    Start time = 20:00 
    End date = Feb 14, 2019 
    End time = 06:00 AM
    

    将输入解析为DateTime 对象还有一些优点,例如可以轻松计算事件的持续时间:

    $duration = $start->diff($end);
    echo "Event is " . $duration->format('%h') . " hours and " . $duration->format('%i') . " minutes long\n";
    

    输出:

    Event is 10 hours and 0 minutes long
    

    Demo on 3v4l.org

    【讨论】:

      【解决方案4】:

      不需要所有繁重的正则表达式的方法是以两种不同的方式使用explode。

      首先,我们在“ - ”上分解不同的 DateTime,然后我们循环并在空间上分解。
      我们知道日期有三个空格,因为有年、月和日。
      使用array_splice 将三个项目作为日期,然后剩下的就是时间。

      $date_range_create_event = "Jan 12, 2019 08:00 PM - Feb 14, 2019 06:00 AM";
      
      $dates = explode(" - ", $date_range_create_event);
      
      foreach($dates as &$date){
          $temp = explode(" ", $date);
          $date = ["date" => implode(" ",array_splice($temp, 0,-2)), "time" => implode(" ", $temp)];
      }
      unset($date);
      

      https://3v4l.org/K4qE7

      【讨论】:

        【解决方案5】:

        试试array_map('date_parse', preg_split('~\s*-\s*~', $date_range_create_event));

        这给出了一个如下所示的数组。剩下的喊就很简单了。

        array(2) {
          [0] =>
          array(12) {
            'year' =>
            int(2019)
            'month' =>
            int(1)
            'day' =>
            int(12)
            'hour' =>
            int(20)
            'minute' =>
            int(0)
            'second' =>
            int(0)
            'fraction' =>
            double(0)
            'warning_count' =>
            int(0)
            'warnings' =>
            array(0) {
            }
            'error_count' =>
            int(0)
            'errors' =>
            array(0) {
            }
            'is_localtime' =>
            bool(false)
          }
          [1] =>
          array(12) {
            'year' =>
            int(2019)
            'month' =>
            int(2)
            'day' =>
            int(14)
            'hour' =>
            int(6)
            'minute' =>
            int(0)
            'second' =>
            int(0)
            'fraction' =>
            double(0)
            'warning_count' =>
            int(0)
            'warnings' =>
            array(0) {
            }
            'error_count' =>
            int(0)
            'errors' =>
            array(0) {
            }
            'is_localtime' =>
            bool(false)
          }
        }
        

        【讨论】:

        • array_map 中的 Preg_split 表示您正在循环正则表达式。正如 OP 所描述的那样,对于“长字符串”来说,这不是一个好主意。
        • 不,@Andreas preg_ 调用没有被迭代,它只被执行一次。拆分的输出是被迭代的内容,这些值被解析为数组。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-01
        • 1970-01-01
        • 2015-06-29
        • 1970-01-01
        相关资源
        最近更新 更多