我正在尝试制作一个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-14
到2003-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.这样的值
谢谢!
诀窍是将文件名和$_POST字段转换为实际日期,然后进行比较。把它们当作数字或字符串处理太有问题了;正则表达式。
此代码处理chl
和lst
的情况。你可以用同样的技巧来称呼别人。请记住,$user_start_date
和$user_end_date
是PHP日期。不是字符串。
在底部,我硬编码了一些开始和结束日期。显然,您将使用$_GET[date']和$_GET[date2']值。DateTime::createFromFormat()的PHP文档包含如何将各种格式的字符串转换为日期的信息。
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);
最后,所有日期格式的范围搜索都开始工作了。
下面的代码来自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
不支持像2001W52
或2001-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})/');