-1

这将有点难以解释,但我会尽我所能解释它。

我将数据从input textfield一个页面(page1.php)传递到Select form另一个页面(page2.php)。这可以正常工作。

the Select Formcontains some PHP timezonesand when a timezone is selected, the page page will echo the current time for that timezone. 这也可以正常工作。

问题是当我在输入文本字段中输入时区名称时(page1.php),它会在选择表单中显示名称,(page2.php)但它不会回显其当前时间,并且会抛出此错误:

Fatal error: Uncaught exception 'Exception' with message 'DateTimeZone::__construct(): Unknown or bad timezone (London)' in page2.php:16 Stack trace: #0 on line 16.

当事实上伦敦时区存在于中时Select Form Options,如果我直接在选择表单中输入/搜索伦敦,它将回显该时区的当前时间,但如果在 page1.php 的输入文本字段中输入了时区名称,则不会它被传递到 page2.php 上的选择表单!

这是我在 page2.php 上的内容:

<?php

if( isset($_POST['submit']))
{
    //be sure to validate and clean your variables
    $timezone2 = htmlentities($_POST['timezone2']);

    //then you can use them in a PHP function. 
    function get_timezone_offset( $remote_tz ) {
        $timezone2 = new DateTimeZone ( $remote_tz ); ----->>> Line 16 is here.

        $datetime2 = new DateTime ("now", $timezone2);

        $offset = $timezone2->getOffset($datetime2);
        return $offset;

    }

$offset = get_timezone_offset($timezone2);

}

?>

<?php
$options = array();
$options[$_POST["location"]] = $_POST["location"]; <<<<<<----- Data from input textfield on page1.php
$options["Africa/Addis_Ababa"] = "Addis Ababa"; <<<<<<----- Select Form Options
$options["Europe/London"] = "London"; <<<<<<----- Select Form Options

?>

这是 page2.php 上的选择表单

<form id="myForm" name="myForm" class="myForm" method="post" action="page2.php">
  <select style="font-size:9px;" name="timezone2" id="timezone2" class="timezone2">
                        <?php
                    foreach($options as $key => $value)
                    {
                        echo '<option value="'. $key .'" label="'. $value .'">'.$value.'</option>';
                    }
                    ?>
<option value="<?php echo $_POST["location"]; ?>"><?php echo $_POST["location"]; ?></option>
</select>
</div>

<div id="myBtn" style="position:relative; float:left; width: 228px; margin-top:50px; margin-left:350px;"><input type="submit" name="submit" id="submit" class="submit" value="Search"/></div>

</form>

这是 page1.php 上的输入文本字段

<form method="post" action="../page2.php">
  <input name="location" type="text" value="Search"/>
  <button type="submit">Search</button>
</form>

有人可以指出我正确的方向吗?

4

1 回答 1

2

出于几个原因,您会犯这个错误。首先,可能的时区列表是有限的,所以去掉文本字段,只使用下拉菜单。

其次,您可以根据需要删除\重命名下拉列表中的项目,但请记住,由于您保存的是偏移量而不是 tz 名称,因此您永远无法返回(我的示例将向您展示如果您使用它的确切原因)。通常,最好存储名称而不是偏移量,以便您可以正确管理夏令时。你会注意到,要让这个系统正常工作,我需要调用 date('I') 来确定它是否是夏令时,这真的很糟糕(仅仅因为我的服务器 TZ 是夏令时并不意味着它在用户 TZ)。如果您保存了 TZ 名称,则可以将该逻辑推迟到 PHP 并使用它当前的任何偏移量。在这个简单的示例中,这似乎并不重要,但是如果您曾经尝试使用它存储该偏移量或计算未来\过去时间,那么您

另一件小事是将函数定义放在“if”语句中很奇怪。在 PHP 中,所有函数定义都是全局的,因此无论“if”条件是否为真,它都将可用。这样做的问题是你现在已经模糊了你的逻辑而没有收获。把它放在别处更容易、更清楚。

我已经重写了你的代码,让它变得更好一点,并在你使用它时实际工作,但我遗漏了一些细节(比如给 TZ 名称加上别名 [你似乎掌握了如何做] 和切换使用 TZ 名称而不是偏移量 [因为这可能会破坏您拥有的其他代码]),但我鼓励您也修复这些问题。

<?php
$tz_offset=0;

function get_offset_time($offset=0) {
    $original=new DateTime("now");
    $timezoneName=timezone_name_from_abbr("", $offset, date('I'));
    if(!$timezoneName) die('ERROR: Unknown timezone \''.($offset/3600).'\'');
    $oTZ=new DateTimezone($timezoneName);
    $modified = $original->setTimezone($oTZ);
    return $modified->format('Y-m-d H:i:s');
}
function get_timezone_offset($tz_name=null) {
    if(!$tz_name) return 0; // If we have invalid data then return before we error
    $tz=new DateTimeZone($tz_name);
    $dt=new DateTime("now", $tz);
    return $tz->getOffset($dt);
}
function enumerate_tz($tz_select=null) {
    global $tz_offset;
    $tz_ident=DateTimeZone::listIdentifiers();
    foreach($tz_ident as $val) {
        $tmp_offset=get_timezone_offset($val);
        if($val=='UTC'||$tmp_offset) 
            echo '<option value="'.$val.'" '. ($tmp_offset==$tz_offset?' selected':''). '>'. 
            $val. ' [ '.($tmp_offset/3600).' ]'.  // If you'd like to customize the viewable names for each TZ you may do so here
                    '</option>';
    }
}
if(isset($_POST['tz_input']) && $_POST['tz_input']) {
    $tz_input=htmlentities($_POST['tz_input']);
    $tz_offset=get_timezone_offset($tz_input);
}
echo '<html><title>Timezone Select</title><body>'.
'<p>The current timezone offset is: '. ($tz_offset? ($tz_offset/3600): '0'). '</p>';
echo '<p>The current time is: '. get_offset_time($tz_offset). '</p>';
echo '<form method=post><select name=tz_input>';
enumerate_tz($tz_offset); // You'll notice that this list duplicates many of the timezones so that after selecting one the next 
                                    // time through it'll often select a different one. If you want to fix that you'll need to save the actually offset name instead of an offset.
echo '</select><input type=submit value=Search />'.
    '</form></body>';
?>

编辑:要注意的另一件事是 PHP 的 timezone_name_from_abbr() 函数不完整。某些时区偏移不会返回 TimeZone 名称。你也必须考虑到这一点。例如,即使 PHP 理解“太平洋/中途”时区,它在进行反向查找时也无法找到它。我已经更新了代码,这样就不会再导致硬错误了。

EDIT2:我可以看到,除非有人向您展示如何使粪便发光,否则您不会快乐。干得好:

function getOptionDX($val, $option_array) {
    if(!isset($option_array)||!is_array($option_array)||!count($option_array)>0||!$val) return null;
    $val=htmlentities($val);
    if(isset($option_array[$val])) return $val;
    $new_val=array_search($val, $option_array);
    return $new_val!==FALSE?$new_val: null;
}

将此添加到您的代码中,并将对 htmlentities 的调用替换为对此的调用:

$timezone2 = getOptionDX($_POST['timezone2'], $options);

最后,更改这一行:

if($timezone2) $offset = get_timezone_offset($timezone2);

如果用户手动输入 TZ 并且正确,则跳过 page2.php。如果您不想更改任何内容,这与可以给出的答案一样接近。事实是,您的逻辑首先是有缺陷的(这并不意味着是刺戳,但这是真的)。

EDIT3: IDK 出了什么问题,但这是我的完整代码清单,其中包含您要求的修复:

<?php
$offset=0; $timezone2='';
$options = array();
$options["Africa/Addis_Ababa"] = "Addis Ababa";
$options["Europe/London"] = "London";
$options["America/Chicago"] = "The Windy City";

function getOptionDX($val, $option_array) {
    if(!isset($option_array)||!is_array($option_array)||!count($option_array)>0||!$val) return null;
    $val=htmlentities(ucwords(strtolower($val)));
    if(isset($option_array[$val])) return $val;
    $new_val=array_search($val, $option_array);
    return $new_val!==FALSE?$new_val: null;
}
function get_timezone_offset( $remote_tz ) {
    $timezone2=new DateTimeZone($remote_tz);
    $datetime2=new DateTime("now", $timezone2);
    $offset=$timezone2->getOffset($datetime2);
    return $offset;
}
if(isset($_POST['location'])) {
    $addLoc=getOptionDX($_POST['location'], $options);
    if(isset($addLoc)) $options[$addLoc]=$_POST['location'];
    else header('Location: '. $_SERVER['SCRIPT_NAME']);
}
if(isset($_POST['timezone2'])) {
    $timezone2=htmlentities($_POST['timezone2']);
    $offset=get_timezone_offset($timezone2);
}
if(isset($_GET['page2'])) {
?>
<form method=post action=?page2>
<select name=timezone2>
<?php foreach($options as $key=>$value) echo "\t".'<option value="'. $key .'"'.(get_timezone_offset($key)==$offset?' selected':'').'>'.$value.'</option>'."\n"; ?>
</select>
<input type=hidden name=location type="text" value="<?php echo $_POST['location']; ?>"/>
</div>
<input type=submit value=Search>
</form>
<p>Current Offset: <?php echo $offset/3600; ?></p>
<p>Current Time: <?php echo gmdate('Y-m-d H:i:s'); ?> UTC</p>
<p>Current Time: <?php echo gmdate('Y-m-d H:i:s', time()+$offset).' '. $timezone2; ?> </p>
<?php
} else {
?>
<form method=post action=?page2>
<input name=location type=text value=""/>
<button type=submit>Search</button>
</form>

<?php
}
?>

我已经对此进行了测试并且知道它有效,如果这还不足以回答您的问题,那么我放弃了。我开始认为您真的想要一种方法来发明不存在的新时区。那是不可能的。您可以像我在这里所做的那样对已经存在的那些进行别名,这与您将得到的一样接近。从逻辑上讲,时区的范围只能从 -12:00 到 +12:00,并且几乎每个已知的时区都已经被考虑在内,所以如果这还不够,你真的别无选择,只能重新考虑你的设计。

于 2013-09-05T14:36:05.343 回答