How to Perform Arithmetic Operations with Dates and Times in progress openedge.
eg: Add day,month,year in given date.
ADD-INTERVAL is your friend. For simple dates and days you can also work with + and -.
ADD-INTERVAL(datetime, interval-amount, interval-unit)
Adds a time interval to, or subtracts a time interval from, a DATE, DATETIME, or DATETIME-TZ value, and returns the new value.
datetime
An expression whose value is a DATE, DATETIME, or DATETIME-TZ.
interval-amount
A signed integer (positive or negative) indicating the amount of time you want > to add to or subtract from datetime value.
interval-unit
A character constant, or a character expression that evaluates to one of the > following time units: ‘years', ‘months', ‘weeks', ‘days', 'hours', ‘minutes', > ‘seconds' or ‘milliseconds'. These values are case insensitive and may be
singular.
Example:
DEFINE VARIABLE dToday AS DATE NO-UNDO.
DEFINE VARIABLE dNow AS DATETIME NO-UNDO.
dToday = TODAY.
DISPLAY dToday LABEL "Today" WITH FRAME frDate SIDE-LABELS 1 COLUMN.
DISPLAY dToday + 1 LABEL "Tomorrow 1" WITH FRAME frDate.
DISPLAY ADD-INTERVAL(dToday, 1, "day") LABEL "Tomorrow 2" WITH FRAME frDate.
DISPLAY ADD-INTERVAL(dToday, 1, "week") LABEL "Next week" WITH FRAME frDate.
DISPLAY ADD-INTERVAL(dToday, -1, "week") LABEL "Last week" WITH FRAME frDate.
DISPLAY ADD-INTERVAL(dToday, 1, "month") LABEL "Next month" WITH FRAME frDate.
DISPLAY ADD-INTERVAL(dToday, 1, "year") LABEL "Next year" WITH FRAME frDate.
dNow = NOW.
DISPLAY dNOW LABEL "Now" WITH FRAME frDateTime SIDE-LABELS 1 COLUMN.
DISPLAY ADD-INTERVAL(dNow, 1, "hour") LABEL "Next hour" WITH FRAME frDateTime.
DISPLAY ADD-INTERVAL(dNow, 30, "minute") LABEL "In 30 minutes" WITH FRAME frDateTime.
DISPLAY INTERVAL( dToday + RANDOM(1,30), dToday, "minutes") LABEL "Difference in minutes".
You can also use INTERVAL to get the difference between two dates or datetimes.
INTERVAL ( datetime1 , datetime2 , interval-unit )
Returns the time interval between two DATE, DATETIME, or DATETIME-TZ values as an INT64 value.
datetime1
An expression whose value is a DATE, DATETIME, or DATETIME-TZ.
datetime2
An expression whose value is a DATE, DATETIME, or DATETIME-TZ.
interval-unit
A character constant, or a character expression that evaluates to one of the
following time units: ‘years', ‘months', ‘weeks', ‘days', 'hours', ‘minutes', > ‘seconds' or ‘milliseconds'. These values are case insensitive and might be
singular.
Related
I'm currently working on a project in which I have a column called 'weekday'. This column contains day numbers 0:6. I'm new to R and want to create a new column that has weekday abbreviations for each number e.g. "0 = Sun, 1 = Mon", etc. Below is an image of my dataframe I am working with. Any help and tips would be much apppreciated.
Image of dataframe
We can add your zero based weekday index to 2017-01-01, which was a Sunday.
x <- c(0:6)
days_abbrev <- substr(weekdays(as.Date("2017-01-01") + x), 1, 3)
days_abbrev
[1] "Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat"
Or using the excellent suggestion by #DarrenTsai we can pass TRUE as the second parameter to weekdays() to use abbreviations:
weekdays(as.Date("2017-01-01") + x, TRUE)
You can do this directly from the date column using %a format...
format(as.Date("2017-01-05"), "%a")
[1] "Thu"
I have a vector of strings that include a repeating pattern of start and end dates for variables collected at a site. Here is the first entry:
"1942-10-06,1996-03-31Snow Depth (in/mm)1942-11-01,1996-03-31Snowfall (in/mm)1942-10-01,1997-12-27Growing Degree DaysHeating Degree DaysAverage Temperature (F/C)Maximum Temperature (F/C)1950-08-01,1970-03-31Observation Time Temperature (F/C)1942-10-01,1997-12-27Minimum Temperature (F/C)1942-10-01,1996-03-31Precipitation (in/mm)"
Can someone help me reformat each string into a table that includes the start date, end date, and variable name?
The below code should work following some assumptions about the way your data are formatted:
Your start dates are in "yyyy-mm-dd" or "yyyy-dd-mm" format and are
followed by a comma,
Your end dates are in the same format as your start dates and follow
a comma, and
Your variable names follow an end date and contain no
numbers.
As alluded to by Oriol Mirosa these assumptions may not hold.
# Your string
string = "1942-10-06,1996-03-31Snow Depth (in/mm)1942-11-01,1996-03-31Snowfall (in/mm)1942-10-01,1997-12-27Growing Degree DaysHeating Degree DaysAverage Temperature (F/C)Maximum Temperature (F/C)1950-08-01,1970-03-31Observation Time Temperature (F/C)1942-10-01,1997-12-27Minimum Temperature (F/C)1942-10-01,1996-03-31Precipitation (in/mm)"
# Extract text matching Assumptions 1-3, respectively, above
library(stringr)
start_dates = str_extract_all(string, "[0-9]{4}-[0-9]{2}-[0-9]{2},")
end_dates = str_extract_all(string, ",[0-9]{4}-[0-9]{2}-[0-9]{2}")
var_names = str_extract_all(string,
",[0-9]{4}-[0-9]{2}-[0-9]{2}([^[0-9]])+")
# Remove the irrelevant bits (e.g., leading/trailing commas)
start_dates = as.Date(gsub(",", "", unlist(start_dates))) #remove ","
end_dates = as.Date(gsub(",", "", unlist(end_dates))) #remove ","
var_names = gsub(",[0-9]{4}-[0-9]{2}-[0-9]{2}", "", unlist(var_names))
# Put into table
X = data.frame("Start_date" = start_dates,
"End_date" = end_dates,
"Var_name" = var_names)
I have a dataframe with one column having all the date info. The new dataframe was created by extracting month-day format so later I could do a group_by.
df1=seq(as.Date('2011-01-01'),as.Date('2011-01-05'),by = 1)
df2=seq(as.Date('2010-12-28'),as.Date('2010-12-31'),by = 1)
df3=seq(as.Date('2011-01-16'),as.Date('2011-01-18'),by = 1)
df=c(df1,df2,df3)
s = format(df,"%m-%d")
s is the new dataframe and is character. s looks like this:
[1] "01-01" "01-02" "01-03" "01-04" "01-05" "12-28" "12-29"
[8] "12-30" "12-31" "01-16" "01-17" "01-18"
How could I detect from "12-28" to "01-05" is consecutive.
If it is in Date format I could use diff to detect, but with character, any suggestion?
Slight problem where my as.Date function gives a different result when I put it in a for loop. I'm looking in a folder with subfolders (per date) that contain images. I build date_list to organize all the dates (for plotting options in a later stage). The Julian Day starts from the first of January of the year, so because I have 4 years of date, the year must be flexible.
# Set up list with 4 columns and counter Q. jan is used to set all dates to the first of january
date_list <- outer(1:52, 1:4)
q = 1
jan <- "-01-01"
for (scene in folders){
year <- as.numeric(substr(scene, start=10, stop=13))
day <- as.numeric(substr(scene, start=14, stop=16))
datum <- paste(year, day, sep='_')
date_list[q, 1] <- datum
date_list[q, 2] <- year
date_list[q, 3] <- day
date_list[q, 4] <- as.Date(day, origin = as.Date(paste(year,jan, sep="")))
q = q+1
}
Output final row:
[52,] "2016_267" "2016" "267" "17068"
What am i missing in date_list[q, 4] that doesn't transfer my integer to a date?
running the following code does work, but due to the large amount of scenes and folders I like to automate this:
as.Date(day, origin = as.Date(paste(year,jan, sep="")))
Thank you for your time!
Well, I assume this would answer your first question:
date_list[q, 4] <- as.character(as.Date(datum,format="%Y_%j"))
as.Date accept a format argument, (the %Y and %j are documented in strptime), the %jis the julian day, this is a little easier to read than using origin and multiple paste calls.
Your problem is actually linked to what a Date object is:
> dput(as.Date("2016-01-10"))
structure(16810, class = "Date")
When entered into a matrix (your date_list) it is coerced to character w
without special treatment before like this:
> d<-as.Date("2016-01-10")
> class(d)<-"character"
> d
[1] "16810"
Hence you get only the number of days since 1970-01-01. When you ask for the date as character representation with as.character, it gives the correct value because the Date class as a as.character method which first compute the date in human format before returning a character value.
Now if I understood well your problem I would go this way:
First create a function to work on one string:
name_to_list <- function(name) {
dpart <- substr(name, start=10, stop=16)
date <- as.POSIXlt(dpart, format="%Y%j")
c("datum"=paste(date$year+1900,date$yday,sep="_"), "year"=date$year+1900, "julian_day"=date$yday, "date"=as.character(date) )
}
this function just get your substring, and then convert it to POSIXlt class, which give us julian day, year and date in one pass. as the year is stored as integer since 1900 (could be negative), we have to add 1900 when storing the year in the fields.
Then if your folders variable is a vector of string:
lapply(folders,name_to_list)
wich for folders=c("LC81730382016267LGN00","LC81730382016287LGN00","LC81730382016167LGN00") gives:
[[1]]
datum year julian_day date
"2016_266" "2016" "266" "2016-09-23"
[[2]]
datum year julian_day date
"2016_286" "2016" "286" "2016-10-13"
[[3]]
datum year julian_day date
"2016_166" "2016" "166" "2016-06-15"
Do you mean to output your day as 3 numbers? Should it not be 2 numbers?
day <- as.numeric(substr(scene, start=15, stop=16))
or
day <- as.numeric(substr(scene, start=14, stop=15))
That could at least be part of the issue. Providing an example of what typical values of "scene" are would be helpful here.
Trying to find a function which can take a date and tell me which day it is,
e.g. if I input today's date, which is "12/29/2014", it will say "it is the 5th Monday of the month" (but doesn't have to be a string output, it can be 5,1 as output representing 5th Mon). It is kinda the opposite of timeNthNdayInMonth in timeDate library which tells you the date given nth nday.
Here's a function f():
f <- function(date)
paste(ceiling(as.numeric(format(date, "%d")) / 7), format(date, "%w"), sep = ",")
f(Sys.Date())