2012-01-17 44 views
6
options(digits.secs = 3); 

> strptime("2007-03-30 15:00:00.007", format = "%Y-%m-%d %H:%M:%OS"); 
[1] "2007-03-30 15:00:00.007" 
> strptime("2007-03-30 15:00:00.008", format = "%Y-%m-%d %H:%M:%OS"); 
[1] "2007-03-30 15:00:00.008" 
> strptime("2007-03-30 15:00:00.009", format = "%Y-%m-%d %H:%M:%OS"); 
[1] "2007-03-30 15:00:00.008" 
> strptime("2007-03-30 15:00:00.010", format = "%Y-%m-%d %H:%M:%OS"); 
[1] "2007-03-30 15:00:00.01" 
> strptime("2007-03-30 15:00:00.011", format = "%Y-%m-%d %H:%M:%OS"); 
[1] "2007-03-30 15:00:00.010" 
> strptime("2007-03-30 15:00:00.999", format = "%Y-%m-%d %H:%M:%OS"); 
[1] "2007-03-30 15:00:00.998" 

Tôi nhầm lẫn lý do tại sao có sự khác biệt một phần nghìn giây từ "009", sau đó lại từ "011".Câu đố mili giây khi gọi strptime trong R

+0

Bạn có thể muốn bao gồm sản lượng từ 'sessionInfo', như tôi có thể không tái tạo hành vi này, vì vậy phiên bản R, hệ điều hành, v.v. của bạn có thể có liên quan. – joran

+0

Làm việc với tôi với R-2.14.1 trên Ubuntu 11,10 64 bit. Bạn đã thử khởi động lại máy tính chưa? –

+0

FWIW, tôi nhận được hành vi tương tự như OP, với R-2.14.1 trên một hộp Windows. –

Trả lời

9

Điều này liên quan đến R-FAQ 7.31, mặc dù nó có một vỏ bọc khác thường hơn.

Hành vi bạn đang thấy kết quả từ sự kết hợp của: (a) đại diện không chính xác (nhiều nhất) giá trị thập phân của máy tính nhị phân; và (b) hành vi được ghi lại của các tài liệu strftimestrptime, là cắt ngắn thay vì vòng các phần phân đoạn của giây, đến số chữ số thập phân được chỉ định.

Từ ?strptime tập tin trợ giúp (các từ khóa là 'cụt'):

cụ thể để R là '% OSn', mà cho sản lượng cung cấp cho các giây cắt ngắn để '0 < = n < = 6 chữ số thập phân (và nếu '% OS' không phải là theo sau là chữ số, nó sử dụng cài đặt của 'getOption ("digits.secs")', hoặc nếu không được đặt, 'n = 3').

Một ví dụ có thể sẽ minh họa những gì đang xảy ra một cách hiệu quả hơn giải thích thêm:

strftime('2011-10-11 07:49:36.3', format="%Y-%m-%d %H:%M:%OS6") 
[1] "2011-10-11 07:49:36.299999" 

strptime('2012-01-16 12:00:00.3', format="%Y-%m-%d %H:%M:%OS1") 
[1] "2012-01-16 12:00:00.2" 

Trong ví dụ trên, các phân đoạn' 0,3' phải được xấp xỉ tốt nhất bởi một số nhị phân đó là hơi ít hơn '0.300000000000000000' - giống như '0.29999999999999999'. Vì strptimestrftime cắt ngắn thay vì tròn thành chữ số thập phân được chỉ định, 0,3 sẽ được chuyển thành 0,2, nếu số vị trí thập phân được đặt thành 1. Cùng một logic giữ cho thời gian ví dụ của bạn, trong đó một nửa thể hiện hành vi này, (trung bình) được mong đợi.

+0

Ngoài sự tò mò, bạn có biết tại sao không Joshua và tôi không thể tái tạo nó trên Ubuntu và OSX? – joran

+0

@joran: nó có thể là một vấn đề của kiến ​​trúc 32bit so với 64bit không?Tôi có thể tái sản xuất vấn đề trên FC16 32bit, do đó, có vẻ như nó không phải là vấn đề hệ điều hành ... – nico

+0

@joran - Không, tôi không có kiến ​​thức, mặc dù tôi bị hấp dẫn. Tôi tự hỏi nếu điều này, từ sâu hơn trong tập tin trợ giúp 'strftime' là một đầu mối:' Hành vi của các thông số chuyển đổi khác (và thậm chí nếu các chuỗi ký tự khác bắt đầu với '%' _are_ conversion specification) là hệ thống cụ thể.' –

2

Tôi biết nó đã được "trả lời" nhưng vấn đề này vẫn tồn tại cho 32 bit R, có sự không thống nhất trong việc triển khai giữa các phiên bản 32 bit và 64 bit. Vấn đề cắt ngắn là một phần đúng nhưng nó không phải là kết quả của hàm strptime mà là phương thức print.POSIXlt trong trường hợp cụ thể này.

Điều này có thể được chứng minh bằng cách ghi đè hàm bằng hàm tạo ra hành vi mong đợi. Ví dụ.

print.POSIXlt = function(posix) { 
    print(paste0(posix$year+1900,"-",sprintf("%02d",posix$mon+1),"-",sprintf("%02d",posix$mday)," ", 
     sprintf("%02d",posix$hour),":",sprintf("%02d",posix$min),":",sprintf("%002.003f",posix$sec))) 
    } 

Bây giờ hiển thị thời gian như mong đợi:

> strptime("2007-03-30 15:00:00.009", format = "%Y-%m-%d %H:%M:%OS"); 
[1] "2007-03-30 15:00:0.009" 

Để biết thêm chi tiết, tôi đã đề cập ở đây R issue with rounding milliseconds