簡體   English   中英

如何在PHP中從時區名稱轉換為時區偏移量,反之亦然

[英]How to convert from timezone name to timezone offset and vice versa in PHP

我有一個充滿用戶的數據庫,每個用戶都有一個以字符串形式存儲的timezone列(例如America/New_York )。 (而且我知道,將它們作為偏移量存儲在數據庫中更有意義,但無法在此項目中完成)。我有一個表格,用戶可以更改其時區。 這是我的第一種方法:

我在其中填充了一個下拉列表( value => display ):

protected $timezones = [
    '+00:00' => '(UTC +00:00) Western European Time',
    '+01:00' => '(UTC +01:00) Central European Time',
    '+02:00' => '(UTC +02:00) Eastern European Time',
    '+03:00' => '(UTC +03:00) Further-Eastern European Time',
    '+04:00' => '(UTC +04:00) Gulf Standard Time',
    '+05:00' => '(UTC +05:00) Pakistan Standard Time',
    '+05:30' => '(UTC +05:30) Indian Standard Time',
    '+05:45' => '(UTC +05:45) Nepal Time',
    '+06:00' => '(UTC +06:00) British Indian Ocean Time',
    '+07:00' => '(UTC +07:00) Thailand Standard Time',
    '+08:00' => '(UTC +08:00) Australian Western Standard Time',
    '+09:00' => '(UTC +09:00) Japan Standard Time',
    '+10:00' => '(UTC +10:00) Australian Eastern Standard Time',
    '+10:30' => '(UTC +10:30) Australian Central Daylight Savings Time',
    '+11:00' => '(UTC +11:00) Australian Eastern Daylight Savings Time',
    '+12:00' => '(UTC +12:00) New Zealand Standard Time',
    '+13:00' => '(UTC +13:00) New Zealand Daylight Time',
    '-01:00' => '(UTC -01:00) Eastern Greenland Time',
    '-02:00' => '(UTC -02:00) Brasilia Summer Time',
    '-03:00' => '(UTC -03:00) Atlantic Daylight Time',
    '-04:00' => '(UTC -04:00) Atlantic Standard Time',
    '-05:00' => '(UTC -05:00) Central Daylight Time',
    '-06:00' => '(UTC -06:00) Central Standard Time',
    '-07:00' => '(UTC -07:00) Pacific Daylight Time',
    '-08:00' => '(UTC -08:00) Pacific Standard Time',
    '-09:00' => '(UTC -09:00) Alaska Standard Time',
    '-10:00' => '(UTC -10:00) Hawaii-Aleutian Standard Time',
    '-11:00' => '(UTC -11:00) Niue Time',
];

此函數將時區字符串轉換為offset:

 /**
 * convert timezone string to offset
 *   e.g. "America/New_York" to "-04:00"
 *
 * @param string $timezone time zone represented as a string
 *
 * @return mixed string or null
 */
protected function convertStringToOffset($timezone)
{
    $time = new \DateTime('now', new DateTimeZone($timezone));
    if ($time) {
        return $time->format('P');
    }
}

這個函數將偏移量轉換為字符串:

/**
 * convert timezone offset to string
 *    e.g. "-04:00" to "America/New_York"
 *
 * @param string $offset time zone represented as a numerical offset
 *
 * @return string time zone represented as a string
 */
protected function convertOffsetToString($offset)
{
    // Calculate seconds from offset
    list($hours, $minutes) = explode(':', $offset);
    $seconds = $hours * 60 * 60 + $minutes * 60;
    // Get timezone name from seconds
    $tz = timezone_name_from_abbr('', $seconds, 1);
    // Workaround for bug #44780
    if ($tz === false) {
        $tz = timezone_name_from_abbr('', $seconds, 0);
    }
    return $tz;
}
  1. 因此,在頁面加載時,我會從數據庫中提取時區並將其轉換為偏移量。 例如, America/New_York將轉換為-04:00並且將選擇(UTC -04:00) Atlantic Standard Time

  2. 現在,用戶將選擇其他時區並提交表單。 然后,我將偏移量轉換為字符串,然后將其存儲到數據庫中。

我遇到了一個問題:

  • $this->convertOffsetToString('+03:00'); 返回Europe/Helsinki
  • $this->convertOffsetToString('+04:00'); 返回Europe/Moscow

但!

  • $this->convertStringToOffset('Europe/Moscow'); 返回+03:00
  • $this->convertStringToOffset('Europe/Helsinki'); 返回+03:00

因此,如果用戶進入表單並在數據庫中具有Europe/Moscow時區,我們會將字符串轉換為其偏移量,獲取+03:00 ,而'(UTC +03:00) Further-Eastern European Time'將是已選擇。

問題 :兩個不同的偏移量(例如+03:00+04:00 )將轉換為兩個不同的字符串時區。 這兩個不同的字符串時區將轉換為相同的偏移量! (例如+03:00 )。 任何人都可以提出安全可擴展的解決方案來解決此問題嗎?

首先,

我知道將它們存儲為偏移量在數據庫中更有意義

不,不是。 偏移量發生變化。 許多時區在一年中的某些時間應用夏時制,並且它們更改的日期/時間會有所不同。

您應該將用戶時區存儲為該列表中的字符串,然后使用該時區創建\\ DateTimeZone實例。 例如:-

$tzString = 'Europe/London';
$tz = new \DateTimeZone($tzString);

然后,您可以使用任何類似的方法在任何時候獲得正確的偏移量:

$tz->getOffset(new \DateTime());

例子 請注意,示例中產生的偏移量將在0到3600之間變化,具體取決於查看日期和時間。

在存儲用戶時區時,您不必面對嘗試將偏移量轉換為正確時區的徒勞。

我建議這是解決您問題的“安全可擴展解決方案”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM