'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.



Solution 1:[1]

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.

Solution 2:[2]

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

Solution 3:[3]

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.


1Essentials of dates and times

Solution 4:[4]

You can try tryFormats

as.Date(x, format, tryFormats = c("%m/%d/%y, %H:%M"),
optional = FALSE)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 VvdL
Solution 3
Solution 4 Jesus Abril