• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

使用PHP构建:自动时区检测

Planner 应用程序作为现实生活中的示例,指导您从概念到现实启动一家初创公司 。在此过程中的每一步,我都会将 Meeting Planner 代码作为开源示例发布,您可以从中学习。我还将解决与启动相关的业务问题。

调度需要s时区

对于Meeting Planner的 alpha 版本,我为人们提供了在用户设置中更改时区的机会。然而,对于美国西部以外的任何人来说,他们可能一直想知道为什么他们的日历约会在错误的时间。您必须知道查找设置页面。

当我接近测试版时,我意识到我需要尽快解决这个问题。所以我开始思考如何最好地解决这个问题。

在今天的节目中,我将向您介绍我的自动时区检测方法以及我如何将其集成到用户体验中。

如果您还没有,请立即通过 安排您的第一次会议来试用 Meeting Planner 。如果您不在太平洋标准时间区域,您可能会看到更新时区的提示,如下所述。请在下面的评论中发布您对体验的反馈。

我确实参与了评论线程,但您也可以  在 Twitter 上与我联系 @reifman 。我总是对未来教程的新功能想法和主题建议持开放态度。

提醒一下,Meeting Planner 的所有代码都是用 php 的 Yii2 F ram ework 编写的。如果您想了解更多关于 Yii2 的信息,请查看我的并行系列 Programming With Yii2我建立的会议策划者越多,我对 Yii2 和他们的志愿者团队的印象就越深刻。

研究时区检测

当前设置页面允许用户选择时区。我拼凑了一个屏幕截图,显示了当您单击下拉菜单时出现的部分选定时区;有很多:

使用PHP构建:自动时区检测  第1张

这似乎运作良好,但用户不一定会寻找它。事实上,他们无法知道他们是否与我们的服务器处于同一时区。

首先,我查看了一些时区地图选择器,看看它们是否有一个简单的答案。我发现有两个名称基本相同: 时区选择器

使用PHP构建:自动时区检测  第2张

和 quicksketch/timezonepicker:基于 jquery 和 ImageMap 的时区选择器虽然我很欣赏图形选择器,但它们不适用于移动设备,并且它们不提供检测。

我找到了一个 Yii2 扩展名为 Timezone detection ,但不清楚它如何确定时区以及它的可靠性。

最终,我使用了一个名为 jsTimezoneDetect的基本javascript解决方案;你可以看到下面的演示页面

使用PHP构建:自动时区检测  第3张

它依赖于您的平台或设备时区设置,而不是使用可能被公司网络、ISP 和vpn误导的地理位置 IP 。它速度快,提高了准确性。

设计用户体验

我的目标是检测用户的时区并允许他们快速更新他们的设置而不会分心。我最关心的用户设置时区的地方是当他们将会议时间添加到新会议时。

例如,当他们单击 会议时间时 旁边的加号图标时:

使用PHP构建:自动时区检测  第4张

例如,如果我住在东部时区的加拿大多伦多并访问 Meeting Planner,它的默认设置是 PST,比我晚三个小时。所以我下午 7:30 以上的会议时间是不正确的。

现在,如果jsTimezoneDetect确定您在与当前用户设置(例如洛杉矶)不同的时区(例如多伦多),它会询问您是否要更改它:

使用PHP构建:自动时区检测  第5张

在上面的屏幕截图中,我使用mac OS日期和时间首选项(右上方)从当前的会议计划设置更改我的时区,并允许我测试更改它。

更新时区后,较早的时间选择将以东海岸时间显示:

使用PHP构建:自动时区检测  第6张

但下次您添加会议时间时,它将在您的正确时区。

简化体验

我不希望用户不得不跳到设置页面进行更改——并在计划会议时失去他们的位置。因此,虽然花费了额外的时间,但我编写了一些ajax,从这个页面为他们更新了时区,以便他们可以继续安排。

在下方,您可以看到单击新时区后,状态会提醒您它已更新,您可以继续添加会议时间而不会丢失您的位置:

使用PHP构建:自动时区检测  第7张

开发代码集成

为了构建它,我开始在上面的 frontend/views/meeting-time/_form.php 上工作。首先,我添加了 JavaScript 来检测时区并管理警报:

<?php ActiveForm::end();
   $this->registerJsFile(MiscHelpers::buildUrl().'/js/jstz.min.js',['depends' => [\yii\web\jqueryAsset::className()]]);
   $this->registerJsFile(MiscHelpers::buildUrl().'/js/meeting_time.js',['depends' => [\yii\web\JqueryAsset::className()]]);
   ?>

我还创建了一些隐藏的表单变量来支持脚本

    <?php $form = ActiveForm::begin();?>
    <?= Basehtml::activeHiddenInput($model, 'url_prefix',['value'=>\common\components\MiscHelpers::getUrlPrefix(),'id'=>'url_prefix']); ?>
    <?= BaseHtml::activeHiddenInput($model, 'tz_dynamic',['id'=>'tz_dynamic']); ?>
    <?= BaseHtml::activeHiddenInput($model, 'tz_current',['id'=>'tz_current']); ?>

这 url_prefix有助于管理开发和生产环境之间的 javaScript 寻址。tz_current 从 MeetingTimeController.php 加载这是用户在 Meeting Planner 中的当前时区设置。tz_dynamic 将由我们的检测脚本填写。 

我还在表单顶部创建了两个警告框,默认情况下将使用其 ID 的css定义隐藏:

<div class="tz_success" id="tz_success">
<div id="w4-tz-success" class="alert-success alert fade in">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<?= Yii::t('frontend','Your timezone has been updated successfully.') ?>
</div>
</div>
<div class="tz_warning" id="tz_alert">
<div id="w4-tz-info" class="alert-info alert fade in">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<?= Yii::t('frontend','Would you like us to change your timezone setting to <span id="tz_new"></span>?') ?>
</div>
</div>

tz_alert如果检测到的时区与您当前的设置不同,则会出现 。 tz_success如果您更改时区,则会出现。 

还要注意空的 span 标签:

...change your timezone setting to <span id="tz_new"></span>?') ?>

该脚本将在那里放置一个 AJAX 链接 tz_detect,您将在我们的脚本中看到该链接。

以下是前端/web/js/meeting_time.js 的摘录:

$(document).ready(function(){
    // detect user timezone
    var tz = jstz.determine(); // Determines the time zone of the browser client
    var timezone = tz.name(); //e.g. 'Asia/Kolhata'
    $('#tz_dynamic').val(timezone);
    // compare to current setting
    if (timezone != $('#tz_current').val()) {
      // set the text span alert
      $('#tz_new').html('<a onclick="setTimezone(\''+timezone+'\')" href="javascript:void(0);">'+timezone+'</a>');
      $('#tz_alert').show();
    }
  });

function setTimezone(timezone) {
  $.ajax({
     url: $('#url_prefix').val()+'/user-setting/timezone',
     data: {'timezone': timezone},
     success: function(data) {
       $('#tz_alert').hide();
       $('#tz_success').show();
       return true;
     }
  });
}

在上面的 $(document).ready()函数中,它调用jsTimezoneDetect()并检查用户当前的时区是否不同。如果是,它将空的 span 标记替换为 JavaScript 链接 setTimezone()显示警告框。

setTimezone函数对 UserSettingController.php 进行 AJAX 调用:

public function actionTimezone($timezone) {
      // set current logged in user timezone than return
      Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
      $user_id = Yii::$app->user->getId();
      UserSetting::setUserTimezone($user_id,$timezone);
      return true;
    }

它无需访问设置页面即可无缝更新时区设置。

然后,JavaScript 关闭警报并显示成功框。

JavaScript 和 AJAX 对我来说总是比 PHP 花费更多的时间来编写,但是 UX 非常适合这个特性。

我发现jsTimezoneDetect在我的所有测试中都快速且完全准确。

将代码应用到设置页面

我决定将这种友好的检测应用到“设置”页面,这样用户就不必单击下拉菜单并滑过几十个时区。

使用PHP构建:自动时区检测  第8张

如果他们单击检测到的时区链接,则会出现已保存的成功警报,并在“本地时区 ”下拉菜单中为他们进行设置 。实际上不需要提交表格。

使用PHP构建:自动时区检测  第9张

为了实现这一点,我为 frontend/web/js/user_setting.js 创建了一个几乎相同的 JavaScript 文件:

$(document).ready(function(){
    // detect user timezone
    var tz = jstz.determine(); // Determines the time zone of the browser client
    var timezone = tz.name(); //e.g. 'Asia/Kolhata'
    $('#tz_dynamic').val(timezone);
    // compare to current setting
    if (timezone != $('#tz_combo').val()) {
      // set the text span alert
      $('#tz_new').html('<a onclick="setTimezone(\''+timezone+'\')" href="javascript:void(0);">'+timezone+'</a>');
      $('#tz_alert').show();
    }
  });

function setTimezone(timezone) {
  $.ajax({
     url: $('#url_prefix').val()+'/user-setting/timezone',
     data: {'timezone': timezone},
     success: function(data) {
       $('#tz_alert').hide();
       $('#tz_success').show();
       $('#tz_combo').val(timezone);
       return true;
     }
  });
}

完成后,它会#tz_combo 使用新时区更新用户的下拉值。

其他注意事项

所有这些都非常适合新用户安排他们的第一次会议。但是会议请求的接收者呢?亲自开会的人大多在同一时区,但电话会议等虚拟会议可能需要不同的时区。

如果您阅读“将 iCal 文件导出到日历”一集,您可能还记得我们在 ics 文件导出中包含了时区设置:

BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
BEGIN:VeventUID:9832@meetingplanner.io
DTSTART:20160506T013000Z
DTEND:20160506T023000Z
DTSTAMP:20160506T013000Z
ORGANIZER;CN=admin:mailto:jeff@lookahead.io
URL;VALUE=URI:http://localhost:8888/mp/index.php/meeting/command?id=45&amp;cmd=10&amp;actor_id=1&amp;k=ESxJU_2ZRhZIgzHFyJAIiC39RhZuLiM_&amp;obj_id=0
ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=robsmith;X-NUM-GUESTS=0:mailto:robsmith@lookahead.me
ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=admin;X-NUM-GUESTS=0:mailto:jeff@lookahead.io
CREATED:
DESCRIPTION:It was fun running into you - let's definitely grab that beer! Website: http://www.patxispizza.com/
LAST-MODIFIED:20160506T013000Z
LOCATION:Patxi's Pizza Ballard 5323 Ballard Ave NW  Seattle  WA 98107
SUMMARY:Meetup for Pizza and Long Delayed Conversation
SEQUENCE:0
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

这可确保收件人在将 .ics 文件导入其日历时看到与组织者相同的时区。

我们所有的会议时间都作为 GMT 时区的通用 unix 时间戳存储在数据库中,并且我们的显示会根据每个用户的本地时区进行调整。

但是,我仍需要将 JavaScript 检测添加到会议计划页面和收件人确认页面,以确保提示他们配置时区以查看正确的会议时间。

展望未来

目前,我正在对 Meeting Planner 的 beta 版本进行代码冲刺。在确认会议后,我正在开发许多与提出更改请求或彻底更改会议相关的功能。这需要对如何使人们的日程安排更容易进行大量的概念性思考。我很快就会写更多关于这个的内容。


文章目录
  • 调度需要s时区
  • 研究时区检测
  • 设计用户体验
    • 简化体验
  • 开发代码集成
  • 将代码应用到设置页面
    • 其他注意事项
  • 展望未来