【问题标题】:How to search range of files using dates in php?如何在php中使用日期搜索文件范围?
【发布时间】:2014-10-09 20:18:09
【问题描述】:

我正在尝试制作一个使用从表单获得的日期范围的 php 文件搜索工具。 我有具有以下模式的目录。有数千个文件,但这只是一个示例。

每日文件夹

 chl-2009-05-08-121000.L2_LAC.x.png
 chl-2009-05-09-111500.L2_LAC.x.png
 chl-2009-05-09-112000.L2_LAC.x.png etc

每周文件夹

lst-2014-W36.png
lst-2014-W37.png
lst-2014-W39.png etc

表单有一个参数字段,它将获取 chl、lst 等。其他字段来自表单日期、星期等输入字段。

所以我想要实现的是,例如,查找文件名范围为2002-04-142003-05-25 的所有文件。我有一个提供日期的变量。

到目前为止,我所做的仅列出了与通配符提供的值完全匹配的文件,但我无法获取日期范围内的所有文件。我尝试了每日文件夹。

$a = glob($datadir."{". $_GET['parameter'] .'-'.  $_GET["date"]. "*,". $_GET['parameter'] .'-'.  $_GET["date2"]. "*}" , GLOB_BRACE);
    foreach($a as $image) 
    {
       echo "<a href='".$image."'>" . basename($image) . "</a><br />";  
    }

我在这里使用通配符的原因是为了避免检查像 112000.L2_LAC.x.png 这样的值。

谢谢!

【问题讨论】:

  • 我检查了两次,我没有看到任何问题
  • I couldn't get range of files ~ How can I get the range of files?
  • 单独构建您的 glob 字符串,例如$g = "...."; echo $g; glob($g); 所以你可以检查它。不要只是假设它正在正确构建。
  • 使用您当前的方案,您需要遍历所有具有共同点的文件,然后遍历它们并检查日期是&gt; 还是&lt;
  • 感谢 Dagon 和 showdev 的建议。我进行了编辑以使其更清晰。

标签: php file search range glob


【解决方案1】:

诀窍是将您的文件名和 $_POST 字段转换为实际日期,然后进行比较。将它们视为数字或字符串和正则表达式太成问题了。

此代码处理chllst 的情况。您可以使用相同的技术来解决其他问题。请记住,$user_start_date$user_end_date 是 PHP 日期。不是字符串。

在底部,我硬编码了一些开始和结束日期。显然,您将改用 $_GET['date'] 和 $_GET['date2'] 值。 The PHP docs for DateTime::createFromFormat() 包含有关如何将各种格式的字符串转换为日期的信息。

function filesInRange($datadir, $parameter, $user_start_date, $user_end_date) {

    $all_files  = array();
    $good_files = array();

    //  first create an array of all the filenames, to keep I/O to a minimum
    foreach (new DirectoryIterator($datadir) as $fileInfo) {
        if ( $fileInfo->isFile() ) {
            $all_files[] = $fileInfo->getFileName();
        }
    }

    switch ($parameter) {

        case 'chl':
        foreach ($all_files as $filename) {
            //  we only operate on filenames that start with "chl". we skip others
            if ( strpos($filename, $parameter) === 0 ) {
                $pattern = '/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})-(?<hour>\d{2})(?<minute>\d{2})(?<second>\d{2})/';
                preg_match($pattern, $filename, $matches);
                $filedate = DateTime::createFromFormat('Y-m-j-His',$matches[0]);
                //  check range
                if ($filedate >= $user_start_date && $filedate <= $user_end_date) {
                    $good_files[ $filedate->getTimestamp() ] = $filename;
                }
            }
        }
        break;

        case 'lst':
        foreach ($all_files as $filename) {
            if ( strpos($filename, $parameter) === 0 ) {
                $pattern = '/(?<year>\d{4})-W(?<week>\d{1,2})/';
                preg_match($pattern, $filename, $matches);
                //  start on Jan 1 and keep adding days until we reach our desired week
                $file_start_date = DateTime::createFromFormat('Y-m-d G:i:s',$matches['year'].'-01-01 00:00:00');
                while ( $file_start_date->format('W') < $matches['week'] ) {
                    $file_start_date->modify('+1 day');
                }
                //  add one week to get the end date
                //  the start day starts on the very first second of the day (00:00:00)
                //  the end date ends on the last second (23:59:59)
                $file_end_date = clone $file_start_date;
                $file_end_date->modify('+8 day');
                $file_end_date->modify('-1 second');

                //  check range
                if ($file_start_date >= $user_start_date && $file_end_date <= $user_end_date) {
                    $good_files[ $file_start_date->getTimestamp() ] = $filename;
                }
            }
        }
        break;

        case 'some_other_format':
        //  handle other formats
        break;

    }
    return $good_files;
}

$start = DateTime::createFromFormat('Y-m-j-His','2013-08-01-121000');
$end   = DateTime::createFromFormat('Y-m-j-His','2015-09-15-121000');

$result1 = filesInRange($datadir, 'lst', $start, $end );

var_dump($result1);

【讨论】:

  • 谢谢!我现在确定,这是正确的方向。该范围内的文件来了,但我收到两个错误。我收到错误 Notice:Undefined property: DirectoryIterator::$isDot .. 和 Notice: Undefined offset: 0 in .. 如何将相同的概念应用于每周?因为它的名字中有W。我还有另一个是 Year - 每个月的第一个字母。例如。表单值为 2012-JFM.tif = 2012-JanuaryFebruaryMarch
  • “未定义属性”错误是因为我的代码中存在语法错误。我将更新我的答案以包含修复程序,并填写 lst 案例。通过检查这两个案例,并阅读 DateTime::createFromFormat() 的文档,您应该能够弄清楚如何填写 2012-JFM 案例。
  • 我将等待您修复未定义通知。我已经设法显示 lst-2014-W36.png 和 yyyy-mm 案例。 2012-JFM 案例有点棘手。这就是我要研究的内容。我可以从 'JFM'='JanuaryFebruaryMarch' 或 'JFM'='JanFebMar' 开始。我什至可以将文件重命名为 JaanFebMar,但我不知道对它们进行排序并获得日期、月份或星期等范围。
  • JFM 格式更改为 YYYY-Jan-Feb-Mar 格式后有效!然后我使用 'substr' 让 YYYY-Jan 更容易让它工作。然后我使用了这个 $pattern = '/(?\d{4})-(?\w{3})/';我有一个问题。我如何对具有此类数据的 $good_files 进行排序 tsm-2013-Jan-Feb-Mar.png
  • 好问题!我认为最高效的方法是创建一个稀疏数组,其键是每个ca3.php.net/manual/en/datetime.gettimestamp.php 的时间戳。我已将其包含在更新的代码中。
【解决方案2】:

终于可以对所有日期格式进行范围搜索了。

以下代码来自 sean9999 的原始帖子。它适用于日期 (YYYY-MM-DD)、月份 (YYYY-MM) 和季节性 = 每月 (YYYY-Jan)。

function filesInRange($datadir, $timeper1, $timeper2, $format, $patternval) {
  $matches=array();
  $good_files = array(); 
  $start = DateTime::createFromFormat( $format,$timeper1);
  $end   = DateTime::createFromFormat( $format,$timeper2);   
  $matches=array(); 

  foreach (new DirectoryIterator($datadir) as $fileInfo) {

    if ( !$fileInfo->isDot() && $fileInfo->isFile() ) {
        //  create a date by parsing the file name
          //$pattern = $patternval ;
          preg_match($patternval, $fileInfo->getFileName(), $matches);
          if ($matches) { 
          $filedate = DateTime::createFromFormat($format, $matches[0]);
          }//  determine if it's between start and end date
          if ($filedate >= $start && $filedate <= $end) {
              $good_files[] = $datadir.$fileInfo->getFileName();
          }
    }
  }

  asort($good_files); 
  return $good_files; 
}

调用日常文件的函数。

$allfiles=filesInRange( "data/". $_GET["parameter"] . "/daily/", $_GET['date'], $_GET['date2'], 'Y-m-j', '/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/');

很遗憾,DateTime::createFromFormat 不支持 2001W522001-W52 等周格式。因此,我不得不另谋出路。所以稍作修改后,我使用了date() 函数。这是每周文件搜索的代码。

function filesInRangeweek($datadir, $timeper1, $timeper2, $format, $patternval) {
 $matches=array();
 $good_files = array(); 
 $start = date($format, strtotime($timeper1));
 $end   = date($format, strtotime($timeper2));   
 $matches=array(); 

 foreach (new DirectoryIterator($datadir) as $fileInfo) {

        if ( !$fileInfo->isDot() && $fileInfo->isFile() ) {
            //  create a date by parsing the file name
              //$pattern = $patternval ;
              preg_match($patternval, $fileInfo->getFileName(), $matches);
              if ($matches) { 
                //echo $matches[0];
              $filedate =date($format, strtotime($matches[0]));
              }//  determine if it's between start and end date
              if ($filedate >= $start && $filedate <= $end) {
                  $good_files[] = $datadir.$fileInfo->getFileName();
              }
        }
  }

  asort($good_files); 
  return $good_files; 
}

调用函数;

$result=filesInRangeweek( "data/lst/weekly/", '2013-W35', '2013-W45',"oW", '/(?<year>\d{4})-W(?<week>\d{2})/');

【讨论】:

    猜你喜欢
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-21
    • 1970-01-01
    • 2018-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多