Conversion of character into datetime in R - r

How to convert a column of character "2020-08-12T04:31:41Z" into datetime. I have tried as.POSIXct() function, but, when I give value to format it returns NA.

You can convert the time using utctime from the anytime package or as_datetime from lubridate like this:
df <- data.frame(date = "2020-08-12T04:31:41Z")
library(anytime)
utctime(df$date, tz="UTC")
#> [1] "2020-08-12 04:31:41 UTC"
library(lubridate)
as_datetime(df$date)
#> [1] "2020-08-12 04:31:41 UTC"
Created on 2022-07-06 by the reprex package (v2.0.1)

You can use strptime which creates a datetime object from the given string
strptime("2020-08-12T04:31:41Z", tz = "UTC", "%Y-%m-%dT%H:%M:%OSZ")

Related

Change of Date format

I have a table with date and temperature, and I need to convert the date from this format 1/1/2021 12:00:00 AM to just 1/1/21. Please help. I tried to add a new column with the new date using this code
SFtemps$Date <- as.Date(strptime(SFtemps$Date, "%m/%d/%y %H:%M"))
but it's not working.
It should be %I to represent hours as decimal number (01–12), not %H, and %y to
years without century (00–99).
x <- "1/1/2021 12:00:00 AM"
format(strptime(x, "%m/%d/%Y %I:%M:%S %p"), "%m/%d/%y")
[1] "01/01/21"
Note that after you re-foramt the time object, it'll be a pure character string and lose all attributes of a time object.
Your string is actually a timestamp, using lubridate you can convert it to the desired format and then leverage stamp function to get your data formatted in the manner that suits you.
org_str <- "1/1/2021 12:00:00 AM"
library("lubridate")
#>
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#>
#> date, intersect, setdiff, union
x <- mdy_hms(x = org_str, tz = "UTC")
sf <- stamp("29/01/1997")
#> Multiple formats matched: "%d/%Om/%Y"(1), "%d/%m/%Y"(1)
#> Using: "%d/%Om/%Y"
sf(x)
#> [1] "01/01/2021"
Created on 2022-04-22 by the reprex package (v2.0.1)
Explanation
Contrary to common perception the date doesn't have a format as such. Only string representation of the date can be of a specific format. Consider the following example. Running code:
x <- Sys.Date()
unclass(x)
will return an integer. This is because1:
Thus, objects of the class Date are internally represented as numbers. More specifically, dates in R are actually integers.
The same is applicable to the POSIX objects
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#>
#> date, intersect, setdiff, union
xn <- now()
class(xn)
#> [1] "POSIXct" "POSIXt"
unclass(xn)
#> [1] 1650644616
#> attr(,"tzone")
#> [1] ""
Created on 2022-04-22 by the reprex package (v2.0.1)
You can always run:
format.Date(lubridate::now(), "%d-%m")
# [1] "22-04"
However, by doing this you are not formatting the date but creating a string representation of the date / timestamp object. Your string representation would have to be converted to timestamp / date object if you want to use it in common date time operations.
Suggestions
Whenever working with date time / date objects I would argue that it's advisable to keep those objects as a correct class maintaining the relevant details (such as time zone in case of timestamps) and only leverage formatting functions when utilising the data in analysis / visual representation, as shown in the sample.
1 Essentials of dates and times
Your format is a bit off. These are two options that work (lubridate is my favorite):
SFtemps <- list()
SFtemps$Date <- '1/1/2021 12:00:00 AM'
> as.Date(strptime(SFtemps$Date, "%m/%d/%Y %r"))
[1] "2021-01-01"
> as.Date(lubridate::mdy_hms(SFtemps$Date))
[1] "2021-01-01"
This will give you the date. If you want to see it as 1/1/2021, use the format function
You can try tryFormats
as.Date(x, format, tryFormats = c("%m/%d/%y, %H:%M"),
optional = FALSE)

Can a datepart be parsed as date object, directly without concatenating the missing datepart

Suppose I have a character vector dt with some months-years stored as character format-
dt <- c("Mar-19", "Apr-19", "May-19")
when I try to convert it into date object, it returns NAs only
as.Date(dt, format = "%b-%y")
[1] NA NA NA
So I have to first concatenate a dummy date say 01 to each object and then parse it as date and thereafter format the vector to show it in original format
format.Date(as.Date(paste0("01-", dt), format = "%d-%b-%y"), "%b-%y")
[1] "Mar-19" "Apr-19" "May-19"
Is there any direct method to parse a truncated date/datepart directly without concatenating and thus avoiding the long route?
zoo has as.yearmon class and function which can convert data with year and month without the date.
dt <- c("Mar-19", "Apr-19", "May-19")
zoo::as.yearmon(dt, '%b-%y')
To get it in character class you can use format with format as required.
format(zoo::as.yearmon(dt, '%b-%y'), '%b-%y')
#[1] "Mar-19" "Apr-19" "May-19"
You can use readr::parse_date for this, but it is still not elegant
library(tidyverse)
dt <- c("Mar-19", "Apr-19", "May-19")
dt %>% parse_date(format = "%b-%y") %>% format("%b-%y")
#> [1] "Mar-19" "Apr-19" "May-19"
Created on 2021-02-01 by the reprex package (v0.3.0)
dt <- c("Mar-19", "Apr-19", "May-19")
lubridate::myd(dt, truncated = 1)
#> [1] "2019-03-01" "2019-04-01" "2019-05-01"
# Created on 2021-02-01 by the reprex package (v0.3.0.9001)
(Related to Conversion of date format %B %Y)
Regards,

Extract time (HMS) from lubridate date time object?

I have the following datetime:
t <- "2018-05-01 23:02:50 UTC"
I want to split it to time and date.
When I apply date(t) I get the date part.
But when I use lubridate's hms, parse_date_time and other functions to do this in "HMS" order I get NA.
I have checked other answers here on SOF but for some reason it gives me NA.
Please advise how to extract it.
I want to understand why:
strftime(t, format="%H:%M:%S")
will do the job but what I am missing in lubridate::hms or parse_date_time?
Is this what you were looking for? It can now be done more simply with hms::as_hms.
> library(lubridate)
> library(hms)
> as_hms(ymd_hms("2018-05-01 23:02:50 UTC"))
23:02:50
> t <- "2018-05-01 23:02:50 UTC"
> as_hms(ymd_hms(t))
23:02:50
My solution is to install library(anytime):
date <- anytime::anydate(t)
time <- strftime(t, format="%H:%M:%S")
What you are missing in lubridate's hms() is that it expects "a character vector of hour minute second triples" as an argument. There's no provision for handling a string which also contains date info. Hence, the output of Sys.Date() or lubridate::now() doesn't work as input to lubridate::hms().
In case you want a tidyverse solution, here's one:
library(tidyverse)
library(lubridate)
now()
#> [1] "2018-08-13 16:41:31 BST"
get_time <- function(time = now()) {
time %>%
str_split(" ") %>%
map_chr(2) %>%
hms()
}
get_time()
#> [1] "16H 41M 31S"
get_time("2018-05-01 23:02:50 UTC")
#> [1] "23H 2M 50S"
Created on 2018-08-13 by the reprex package (v0.2.0).
Something like this?
library(hms)
t <- "2018-05-01 23:02:50 UTC"
unlist(strsplit(t," "))[2]%>%hms::parse_hms()
Here is a solution without including just another package (hms on top of lubridate):
t <- "2018-05-01 23:02:50 UTC"
sprintf("%02d:%02d:%02d", hour(t), minute(t), second(t))
"23:02:50"
The fucntion in Lubridate package exists, it is called "hour()", here the official guide:
https://lubridate.tidyverse.org/reference/hour
t <- "2018-05-01 23:02:50 UTC"
lubridate::hour(t)
Posting a solution that I have used to extract either ymd or the hms independently after a lubridate conversion. I noticed OP mentioned wanting to separate both time and date so for future SO users who may find themselves here I included the regex's used for both below. assuming df contains a column called date where time is formated ymd_hms like so "2018-05-01 23:02:50 UTC":
library(stringr)
df <- df %>%
mutate(
time = str_extract(date, "[0-9]{2}:[0-9]{2}:[0-9]{2}") #to extract hms time
day = str_extract(date, "[0-9]{4}-[0-9]{2}-[0-9]{2}") #to extract ymd time
)

Parse date using lubridate in R

I want to parse date format like "Apr-13", "May-14", which I want to parse it to POSIX time "2013-04-01 UTC", "2014-05-01 UTC". I tried using lubridate package in R:
parse_date_time("Apr-13", "my")
parse_date_time("Apr-13", "by")
parse_date_time("Apr-13", "%b-%y")
parse_date_time("Apr-13", "%m-%y")
fast_strptime("Apr-13", "%b-%y")
But all of them failed to parse, is it possible to parse this using lubridate? Any other package is also welcome.
Try this example:
library(lubridate)
x <- c("Apr-13", "May-14")
#add DD as 01
x <- paste("01",x,sep="-")
#result
dmy(x)
#output
#[1] "2013-04-01 UTC" "2014-05-01 UTC"

Convert Date to POSIXct

Why does the Date below change to "2014-07-07" when converted to POSIXct?
Sys.setenv(TZ='America/Sao_Paulo')
d <- as.Date("2014-07-08", format="%Y-%m-%d")
d
[1] "2014-07-08"
as.POSIXct(d)
[1] "2014-07-07 21:00:00 BRT"
Because as.POSIXct.Date doesn't look for a timezone (and won't pass it to .POSIXct if you specify it in ...) and Date objects are "UTC", so your POSIXct is offset from the UTC of the Date object.
It would be better to call as.POSIXct on the character string directly, if you can:
> as.POSIXct("2014-07-08", format="%Y-%m-%d")
[1] "2014-07-08 BRT"

Resources