You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言suncalc包日期/时区计算错误问题求助

解决suncalc包getSunlightTimes函数日期偏移问题

问题描述

在为动物追踪数据添加黎明/黄昏/夜晚/白昼变量时,使用suncalc包的getSunlightTimes函数出现日期偏差。所有时区设置为UTC,系统时区为Pacific/Auckland。例如输入日期为2021-02-05时,得到的日出时间为2021-02-04 17:42:24,日落时间为2021-02-05 07:28:19,地点位于新西兰附近(lon = 174.9776,lat = -36.20939),时段合理但日期偏移一天。

示例数据框

datetime <- c("2021-02-05 11:00:00", "2021-02-05 13:00:00", "2021-02-05 15:00:00")
lat <- c("-36.20939", "-36.20952", "-36.20979")
lon <- c("174.9776", "174.9772", "174.9764")
date <- c("2021-02-05", "2021-02-05", "2021-02-05")

df <- cbind.data.frame(datetime, lat, lon, date)

当前代码

#Using the SunCalc package get times for sunrise, sunset, night, and nightENd
df$datetime <- strptime(df$datetime, format = "%d/%m/%y %H:%M", tz = "UTC")
df$datetime <- as.POSIXct(df$datetime)
df$date <- as.Date(df$datetime, tz = "UTC")

sun_all <- getSunlightTimes(data = df, 
                            tz = "UTC",
                            keep = c("sunrise", "sunset", "night", "nightEnd"))

#Append to main data frame
df$sunrise <- sun_all$sunrise
df$sunset<- sun_all$sunset
df$night <- sun_all$night
df$nightEnd<- sun_all$nightEnd

#Create new column labelling each data point as the Time of Day (ToD)
df$period <- rep(" ", length.out = nrow(df))

# Assign labels based on time ranges
df$period[df$datetime > df$sunrise & df$datetime < df$sunset] <- "day"
df$period[df$datetime > df$sunset & df$datetime < df$night] <- "dusk"
df$period[df$datetime > df$nightEnd & df$datetime < df$sunrise] <- "dawn"
df$period[df$period == " "] <- "night"

问题原因

  1. 日期解析格式错误:当前代码用%d/%m/%y解析datetime列,但输入的日期格式是YYYY-MM-DD HH:MM:SS,格式不匹配导致解析错误,后续日期计算全部出错。
  2. 时区不匹配导致跨天偏移:新西兰(Pacific/Auckland时区)夏季比UTC早13小时,当地日期2021-02-05对应的UTC时间范围是2021-02-04 11:00到2021-02-05 11:00。用UTC时区计算当地日照时间,结果的UTC日期会与当地日期跨天,造成日期偏移的视觉错觉。

解决方案

修正步骤

  1. 正确解析datetime列:使用匹配的格式字符串%Y-%m-%d %H:%M:%S解析日期时间,设置对应时区。
  2. 使用当地时区计算日照时间:将getSunlightTimes的tz参数设置为Pacific/Auckland,确保计算出的日照时间与当地日期对齐。
  3. 优化时段判断逻辑:用更清晰的条件判断语句替代重复赋值。

修正后的代码

library(suncalc)
library(dplyr)

# 示例数据框
datetime <- c("2021-02-05 11:00:00", "2021-02-05 13:00:00", "2021-02-05 15:00:00")
lat <- c("-36.20939", "-36.20952", "-36.20979")
lon <- c("174.9776", "174.9772", "174.9764")
date <- c("2021-02-05", "2021-02-05", "2021-02-05")

df <- cbind.data.frame(datetime, lat, lon, date)

# 1. 正确解析datetime,设置为Pacific/Auckland时区
df$datetime <- as.POSIXct(df$datetime, format = "%Y-%m-%d %H:%M:%S", tz = "Pacific/Auckland")
df$date <- as.Date(df$datetime, tz = "Pacific/Auckland")

# 2. 用当地时区计算日照时间
sun_all <- getSunlightTimes(
  data = df, 
  tz = "Pacific/Auckland",
  keep = c("sunrise", "sunset", "night", "nightEnd")
)

# 合并数据
df <- cbind(df, sun_all)

# 3. 优化时段判断逻辑
df$period <- case_when(
  df$datetime > df$sunrise & df$datetime < df$sunset ~ "day",
  df$datetime > df$sunset & df$datetime < df$night ~ "dusk",
  df$datetime > df$nightEnd & df$datetime < df$sunrise ~ "dawn",
  TRUE ~ "night"
)

# 查看结果
print(df)

关键说明

  • 使用Pacific/Auckland时区计算日照时间,得到的日出日落时间会与当地日期对齐,比如2021-02-05的日出时间显示为当地时间2021-02-05 06:42左右,避免跨天偏移。
  • dplyr::case_when让时段判断逻辑更简洁清晰,减少代码冗余。

内容的提问来源于stack exchange,提问作者squid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:03:11