How can I parse milliseconds correctly?
as.POSIXct function works as following in my environment.
> as.POSIXct("2014-02-24 11:30:00.001")
[1] "2014-02-24 11:30:00.000 JST"
> as.POSIXct("2014-02-24 11:30:00.0011")
[1] "2014-02-24 11:30:00.001 JST"
My R version is x86 v3.0.2 for Windows.
Specify the input format, using %OS to represent the seconds with their fractional parts.
x <- c("2014-02-24 11:30:00.123", "2014-02-24 11:30:00.456")
y <- as.POSIXct(x, format = "%Y-%m-%d %H:%M:%OS")
When you come to display the value, append a number between 0 and 6 to the format string to tell R how many decimal places of seconds to display.
format(y, "%Y-%m-%d %H:%M:%OS6")
## [1] "2014-02-24 11:30:00.122999" "2014-02-24 11:30:00.456000"
(Note that you get rounding errors, and R's datetime formatting always rounds downwards, so if you show less decimal places it sometimes looks like you've lost a millisecond.)
Datetime formats are documented on the ?strptime help page. The relevant paragraph is:
Specific to R is '%OSn', which for output gives the seconds
truncated to '0 <= n <= 6' decimal places (and if '%OS' is not
followed by a digit, it uses the setting of
'getOption("digits.secs")', or if that is unset, 'n = 3').
Further, for 'strptime' '%OS' will input seconds including
fractional seconds. Note that '%S' ignores (and not rounds)
fractional parts on output.
Related
I use this:
want=as.Date(date, '%d-%b-%y')
to convert dates like this: 1-JAN-52
Instead of returning '1952-01-01' I am getting '2052-01-01'. Any advice?
Welcome to modern computers, all shaped after the early Unix systems of the 1970s. The start of time, so to speak, is the epoch, aka 1 Jan 1970.
Your problem here, in a nutshell, is the inferior input data. You only supply two years and by a widely followed convention, values less than 70 are taken for the next century. It's all about the epoch.
So you have two choices. You could preprend '19' to the year part and parse via %Y, or you could just take the year value out of the date and reduce it by 100 if need be.
Some example code for the second (and IMHO better) option, makeing 1970 the cutoff date:
> datestr <- "1-Jan-52"
> d <- as.Date(datestr, '%d-%b-%y')
>
> d
[1] "2052-01-01"
>
> if (as.integer(strftime(d, "%Y")) >= 1970) {
+ dp <- as.POSIXlt(d)
+ dp$year <- dp$year - 100
+ d <- as.Date(dp)
+}
> d
[1] "1952-01-01"
>
You need to go via POSIXlt to get the components easily.
I can convert strings containing hour, minute or second specifications to a difftime:
> as.difftime("12 h", "%H")
Time difference of 12 hours
> as.difftime("12 m", "%M")
Time difference of 12 mins
> as.difftime("12 s", "%S")
Time difference of 12 secs
But I can't do so with a week specification, because there is no appropriate format …, although "weeks" is a legitimate unit of difftime:
> as.difftime("12 w", "%…")
Am I overlooking something?
Roland noted:
It doesn't work beyond hours. … obvious, if you study the code. The relevant part is
difftime(strptime(tim, format = format), strptime("0:0:0", format = "%X"), units = units)
. If you specify only a time for strptime it adds the current date.
Indeed it is easy to study the code in the R Console:
> as.difftime
function (tim, format = "%X", units = "auto")
{
if (inherits(tim, "difftime"))
return(tim)
if (is.character(tim)) {
difftime(strptime(tim, format = format), strptime("0:0:0",
format = "%X"), units = units)
}
else {
if (!is.numeric(tim))
stop("'tim' is not character or numeric")
if (units == "auto")
stop("need explicit units for numeric conversion")
if (!(units %in% c("secs", "mins", "hours", "days", "weeks")))
stop("invalid units specified")
.difftime(tim, units = units)
}
}
The crux of the matter is that the use of strptime causes a time interval character string given to as.difftime to be treated as a point in time, from which 0 h of the
current day is subtracted. This for various reasons makes as.difftime with a string unusable for days and weeks, for example a value of 0 days is not accepted by strptime, although it were perfectly valid as an interval.
A request for comments on the R-devel mailing list didn't elicit wide response. (I received some valuable thoughts from Emil Bode by private mail, thus I won't reproduce them here.) So, I'll refrain from proposing a change to as.difftime, also because changing it would introduce discrepances between R versions.
I want to convert a decimal number to hex format in a way that only bit corresponding to that decimal number is set. For example, for input 0, bit 0 should be set and results in
> paste("0x", sprintf("%032x",2^(0)),sep="")
[1] "0x00000000000000000000000000000001"
and for 1, bit one should be set, resulting in
> paste("0x", sprintf("%032x",2^(1)),sep="")
[1] "0x00000000000000000000000000000002"
This works till 30
> paste("0x", sprintf("%032x",2^(30)),sep="")
[1] "0x00000000000000000000000040000000"
but does not work for values larger than that
> paste("0x", sprintf("%032x",2^(32)),sep="")
Error in sprintf("%032x", 2^(32)) :invalid format '%032x'; use format %f, %e, %g or %a for numeric objects
Any idea how to get around this?
I think you're "overloading" the sprintf function. That is, your type is set to "%032x" and then you pass in the value 2^(32) which the function doesn't see as "%032x" so you get an error.
Here's a couple of semi-related questions, but I don't think these would count as exact duplicates:
why causes invalid format '%d in R?
hex to string formatting conversion in python
Why does a 32-bit OS support 4 GB of RAM?
In below code, the last and the second last R codes produce a bit different result, why? After running the last line why don't I get output "time difference is Time difference of 5 mins"?
how could I get such output?
filenames <- c("CH7Data_20130401T130110.csv", "CH7Data_20130401T130610.csv")
timestamps <- gsub(".*_([^.]+).*", "\\1", filenames)
## [1] "20130401T130110" "20130401T130610"
timestamps <- as.POSIXlt(timestamps, format = "%Y%m%dT%H%M%S")
## [1] "2013-04-01 13:01:10 PDT" "2013-04-01 13:06:10 PDT"
timestamps[2]-timestamps[1]
##Time difference of 5 mins
cat("time difference is",timestamps[2]-timestamps[1])
##time difference is 5
'difftime'-objects are atomic objects with a special class so they have a print method that changes the output seen at the console. If you want as stated in the comment to print a redundant message that includes what comes to the console and some sort of preamble, then this would work:
> cat("time difference is",capture.output(timestamps[2]-timestamps[1]) )
time difference is Time difference of 5 mins
You could inset a line feed at the end of your preamble text:
> cat("time difference is\n",capture.output(timestamps[2]-timestamps[1]) )
time difference is
Time difference of 5 mins
Try
diff = timestamps[2]-timestamps[1]
cat("time difference is",diff,attr(diff,"units"),"\n")
From the help of strptime and as.POSIXct, the POSIXlt and POSIXct classes seem only to record whole seconds.
(I need the milliseconds to pass them as a seed to a random number generator in a shared object.)
You can set the printed times to sub-second accuracy by changing the options:
options("digits.secs"=6)
The maximum is 6 digits - see options
Then you can get the system time to millisecond accuracy using:
as.POSIXlt(Sys.time())
That will print the time. To get the milliseconds since midnight that you're after simply use:
mySeed = as.POSIXlt(Sys.time())
mySeed = 1000*(mySeed$hour*3600 + mySeed$min*60 + mySeed$sec)
?Sys.time says:
On almost all systems it will have sub-second accuracy, possibly
microseconds or better. On Windows it increments in clock ticks
(usually 1/60 of a second) reported to millisecond accuracy.
So you can simply do this:
> foo <- Sys.time()
> foo
[1] "2014-05-22 12:40:55 CEST"
> hours <- as.POSIXlt(foo)$hour
> minutes <- as.POSIXlt(foo)$min
> seconds <- as.POSIXlt(foo)$sec
> hours*60*60*1000+minutes*60*1000+seconds*1000
[1] 45655771
In light of the help page, your results will depend on your system.
If you want to print the milliseconds, you can do this:
> options(digits.secs=3)
> foo
[1] "2014-05-22 12:40:55.771 CEST"