如何在R中自定义纽约交易时区并转换多时区时间戳?
Alright, let's break down how to solve this problem—focusing first on a base-R solution since that's your priority, then touching on a simpler alternative with the lubridate package.
Core Concept
The goal is to map the New York trading window (18:00 NY time to 17:00 next NY day) to a virtual "trading timezone" where this interval becomes 00:00 to 23:00. The process boils down to:
- Convert input timestamps (from Japan, Australia, Moscow) to New York time.
- Adjust each timestamp to fit the custom 00:00-23:00 window based on where it falls in the NY trading day.
Base-R Implementation
This approach uses only built-in R functions, no external packages required. It automatically handles New York's daylight saving time thanks to R's native timezone handling.
Step 1: Define the Conversion Function
convert_to_custom_trading_tz <- function(timestamps, input_tz) { # Convert input timestamps to POSIXct with their original timezone ny_time <- as.POSIXct(timestamps, tz = input_tz) # Switch timezone to New York attr(ny_time, "tzone") <- "America/New_York" # Extract hour component to determine trading window ny_hour <- as.integer(format(ny_time, "%H")) # Initialize trading date and time variables trading_date <- as.Date(ny_time) trading_time <- ny_time # Adjust for timestamps before 18:00 NY time (fall into previous trading day) before_18 <- ny_hour < 18 trading_date[before_18] <- trading_date[before_18] - 1 trading_time[before_18] <- trading_time[before_18] + 6 * 3600 # Add 6 hours to reach 00:00+ # Adjust for timestamps at/after 18:00 NY time (fall into current trading day) after_eq_18 <- !before_18 trading_time[after_eq_18] <- trading_time[after_eq_18] - 18 * 3600 # Subtract 18 hours to reach 00:00+ # Combine date and time into the custom trading datetime custom_trading_dt <- as.POSIXct( paste(trading_date, format(trading_time, "%H:%M:%S")), tz = "UTC" ) # Label with our custom timezone for clarity (technical storage is UTC) attr(custom_trading_dt, "tzone") <- "Custom_Trading_TZ" return(custom_trading_dt) }
Step 2: Test with Sample Timestamps
Let's test with timestamps from each target timezone:
# Test Japan Time (Asia/Tokyo) japan_times <- as.POSIXct(c("2024-06-01 10:00:00", "2024-06-01 05:00:00"), tz = "Asia/Tokyo") convert_to_custom_trading_tz(japan_times, "Asia/Tokyo") # Expected output: # [1] "2024-05-31 03:00:00 Custom_Trading_TZ" "2024-05-31 23:00:00 Custom_Trading_TZ" # Test Sydney Time (Australia/Sydney) sydney_times <- as.POSIXct(c("2024-06-01 12:00:00", "2024-06-01 06:00:00"), tz = "Australia/Sydney") convert_to_custom_trading_tz(sydney_times, "Australia/Sydney") # Expected output: # [1] "2024-05-31 05:00:00 Custom_Trading_TZ" "2024-05-31 21:00:00 Custom_Trading_TZ" # Test Moscow Time (Europe/Moscow) moscow_times <- as.POSIXct(c("2024-06-01 20:00:00", "2024-06-01 10:00:00"), tz = "Europe/Moscow") convert_to_custom_trading_tz(moscow_times, "Europe/Moscow") # Expected output: # [1] "2024-06-01 01:00:00 Custom_Trading_TZ" "2024-05-31 17:00:00 Custom_Trading_TZ"
Alternative: Lubridate Package (Simpler Syntax)
If you're open to using external packages, lubridate simplifies the code with more intuitive date-time functions:
Step 1: Install and Load Lubridate
install.packages("lubridate") library(lubridate)
Step 2: Define the Lubridate Conversion Function
convert_to_custom_trading_tz_lubridate <- function(timestamps, input_tz) { # Convert input to NY time ny_time <- force_tz(as_datetime(timestamps), tzone = input_tz) %>% with_tz("America/New_York") # Initialize trading date/time trading_date <- date(ny_time) trading_time <- ny_time # Adjust for pre-18:00 NY times pre_trading_hours <- hour(ny_time) < 18 trading_date[pre_trading_hours] <- trading_date[pre_trading_hours] - days(1) trading_time[pre_trading_hours] <- trading_time[pre_trading_hours] + hours(6) # Adjust for post-18:00 NY times trading_time[!pre_trading_hours] <- trading_time[!pre_trading_hours] - hours(18) # Combine and label custom timezone custom_trading_dt <- ymd_hms( paste(trading_date, format(trading_time, "%H:%M:%S")), tz = "UTC" ) attr(custom_trading_dt, "tzone") <- "Custom_Trading_TZ" return(custom_trading_dt) }
Key Notes
- Daylight Saving Time: Both solutions automatically handle NY's DST changes because we convert timestamps to the
America/New_Yorktimezone, which R recognizes with built-in DST rules. - Custom Timezone Label: The
Custom_Trading_TZlabel is just for readability—under the hood, the datetime is stored in UTC, but the logic aligns perfectly with your desired 00:00-23:00 trading window. - Base-R vs Lubridate: The base-R version is ideal for environments where external packages aren't allowed, while lubridate offers cleaner, more readable code for everyday use.
内容的提问来源于stack exchange,提问作者Denis

