如何在使用Shiny时检索客户端的当前时间和时区?

时间:2014-07-19 15:59:51

标签: r timezone shiny

我想知道是否有一些聪明的方法来获取客户端当前的时间和时区,以便在Shiny应用程序的server.R部分中使用它。如果没有,最简单的方法是什么?

4 个答案:

答案 0 :(得分:1)

我找到了一个有效的方法,它只是对Reading javascript variable into shiny/R on app load的stackoverflow答案的一个小修改。它不会检索实际时区,但会检索时区偏移。

在ui.R

HTML('<input type="text" id="client_time" name="client_time" style="display: none;"> '),
HTML('<input type="text" id="client_time_zone_offset" name="client_time_zone_offset" style="display: none;"> '),

tags$script('
  $(function() {
    var time_now = new Date()
    $("input#client_time").val(time_now.getTime())
    $("input#client_time_zone_offset").val(time_now.getTimezoneOffset())
  });    
')

上面创建了两个div,javascript代码检索客户端的时间和时区偏移量并将它们放在div s中。

在server.R

client_time <- reactive(as.numeric(input$client_time) / 1000) # in s
time_zone_offset <- reactive(as.numeric(input$client_time_zone_offset) * 60 ) # in s 

上面创建了两个可以在服务器代码中使用的反应变量。为了便于处理,我还将input$client_time从ms转换为s,将input$client_time_zone_offset从min转换为s。

答案 1 :(得分:0)

您可以通过套接字通信获取它,但是开销很大,或者如果您在客户端之间的时间同步,您可以信任当地时间,获取时区,评估服务器和客户端之间的时区差异,以及/减去差异,那么你就可以在没有多少工作的情况下获取他们的时间和时区。 (不知怎的,但在大多数情况下,通过这样做,由于计算机的跟踪,会丢失2到3秒的精度)

答案 2 :(得分:0)

直到你的帖子,我才听说过Shiny。阅读文档,似乎Shiny应用程序的客户端部分是用R编写的,但随后呈现为HTML / CSS / JavaScript,因此它可以在浏览器中运行。您要求的信息必须来自JavaScript。

在JavaScript中获取当前时间非常简单:

var now = new Date();

结果是一个Date对象,它具有来自客户端时钟的当前日期和时间。在内部,它被跟踪为自UTC时间午夜1点17分以来的UTC时间(以毫秒为单位)。但是,Date对象在生成.toString()等输出或使用许多其他功能时会考虑客户端的本地时区。您可以在MDN reference documentation中了解有关Date对象的更多信息。

现在,如果你真的需要客户的时区,这是一个不同的故事。 Date对象只能使用.getTimezoneOffset()函数为您提供特定日期和时间的时区 offset 。例如,您可以告诉客户端当前比UTC晚了420分钟(UTC-07:00),但您无法判断客户端是否位于America/Los_Angeles时区 - 在UTC-07:00之间交替和UTC-08:00用于夏令时。阅读the timezone tag wiki中的更多内容。

有一个JavaScript库jsTimeZoneDetect,它试图猜测时区,并且它的工作做得相当不错。

所以 - 现在的问题是,你如何从R中的Shiny应用调用自定义JavaScript?我不是这方面的专家,但它似乎被this part of the Shiny documentation覆盖。

所有这些都将在客户端完成。然后,您必须将其发送到服务器以使用server.R部分应用程序中的信息。

答案 3 :(得分:0)

另一种方法:随时向客户端发送消息,并使用输入对象检索结果。您还将测量延迟。 (或者,如果用户在闪亮会话期间更改了时区......)。

获取服务器时间和时区,通过sendCustomMessage将其发送到客户端。

# R
triggerClientTime <- function(session=shiny::getDefaultReactiveDomain()){
  serverTime <- Sys.time()
  serverTimeZone <- as.integer(strftime(serverTime,"%z"))/100
session$sendCustomMessage(
  type="getClientTime",
  message=list(
    serverPosix = as.numeric(serverTime),
    serverTimeZone = serverTimeZone
    )
  )
}

将此功能放入服务器文件中。

在javascript中,获取消息,检索时间和区域偏移,将其作为新输入条目发送回服务器:

// js
  Shiny.addCustomMessageHandler("getClientTime",
      function(s){
        var d = new Date()
        var clientPosix = parseInt(d.getTime()/1000);
        var clientTimeZone = -(d.getTimezoneOffset() / 60);
        var res =  {
          serverPosix:s.serverPosix,
          serverTimeZone:s.serverTimeZone,
          clientPosix:clientPosix,
          clientTimeZone:clientTimeZone
        }
        Shiny.onInputChange("clientTime",res)
      })

将此代码放在脚本标记或单独的js文件中。

在闪亮的会议中:

# Observe and print time from client and server
  observe({ 
    print(input$clientTime)
  })
# Ask the client for current time and time zone (hours from UTC)
  triggerClientTime()

它应该输出如下内容:

# output
$serverPosix
[1] 1449827815

$serverTimeZone
[1] 1

$clientPosix
[1] 1449827816

$clientTimeZone
[1] 1