abas-ERP (FO- Language): Getting Weekday of abas date - erp

Is there any FO function for getting the weekday of an abas date as short. e.g.:
Today: 07.04.2016 -> Thursday (th) ?

In example, when you have;
.type GD xddate ? _F|defined(U|xddate)
.type int xidate ? _F|defined(U|xidate)
..
!START
.formula U|xddate = "."
.formula U|xidate = U|xddate//7
.println 'F|tostring(U|xidate)'
The variable U|xtdate will continue "4" which is the fourth day of the week, Thursday.

Another deeper approach would be, to get the name of the weekday from the built-in dictionary.
See in HOMEDIR/msg.cc.dic which number monday has (in my case 420)
Then this FO-line
.type text xtweekday
.type GD xddate
.formula U|xddate = "09.04.2016"
.atext -language E xtweekday 'F|eval(420 + U|xddate//7)'
'xtweekday' returns Saturday
for "today" just write
.atext -language E xtweekday 'F|eval(420 + G|date//7)'
You can also use the more powerfull .translate command, but this is in this case not really necessary.

Related

Date with Gaps - Wavelet Analysis in R Using Biwavelet Package

I am performing Wavelet Analysis using biwavelet package in R. The date variable does not have continuous dates but with gaps. When I try to create the graph, I get the following error.
Error in check.datum(d) : The step size must be constant (see approx function to interpolate)
An MWE is given below:
library(foreign)
library(biwavelet)
library(xts)
library(labelled)
library(zoo)
date =c("2020-02-13", "2020-02-14", "2020-02-17", "2020-02-18", "2020-02-19", "2020-02-20", "2020-02-21", "2020-02-24", "2020-02-25", "2020-02-26", "2020-02-27", "2020-02-28", "2020-03-02", "2020-03-03", "2020-03-04", "2020-03-05", "2020-03-06", "2020-03-09", "2020-03-10", "2020-03-11", "2020-03-12", "2020-03-13")
rdate = as.Date(date)
date <- as.Date(date, format = "%Y-%m-%d")
date
class(date)
var = c(-0.077423148, -0.083293147, -0.089214072, -0.095185943, -0.101208754, -0.107282504, -0.113407195, -0.119582824, -0.125809386, -0.125806898, -0.132149309, -0.138584509, -0.145112529, -0.151733354, -0.158446968, -0.165253401, -0.172152638, -0.179144681, -0.186229542, -0.193407193, -0.200677648, -0.208040923)
data = data.frame(date, var)
View(data)
X <- as.xts(data[,-1], order.by = date)
ABC <- data.frame(date, var)
wt.t1=plot(wt(ABC), form = "%b-%d")
How can I resolve this issue?
You can interpolate missing days by following the instructions in the error message:
alldates <- seq(min(date), max(date), by = 1)
interpdata <- approx(date, var, xout = alldates)
ABC <- data.frame(date = alldates, var = interpdata$y)
wt.t1 <- plot(wt(ABC, form = "%b-%d")
However, I think the reason you are missing some days is that they are Saturday or Sunday; I only see weekdays in the dataset.
For many datasets (e.g. stock market trading, etc.) it doesn't make sense to interpolate "what would the price have been on Saturday?", because trades never occur on Saturday or Sunday. In that case, I'd suggest replacing the "date" variable with a simple increment, e.g.
date <- 1:length(date)
ABC <- data.frame(date, var)
wt.t1=plot(wt(ABC), form = "%b-%d")

Convert month (date) into full month (string)

I have a date field (adate10) called Period with values like 07/02/2018.
I need to convert this into a string like "July 2, 2018."
I can use the code below to produce a string, Period_String, that says "JUL 2, 2018." I can't figure out how to format the month as the full month, e.g., "July." Is the only option to create an if/then statement that says 'if 1 then "January", if 2, then "February"', etc.? Was hoping there was a built in format but can't find it.
* extract each date element, then format.
compute mo = xdate.month(Period).
compute da = xdate.mday(Period).
compute yr = xdate.year(Period).
formats mo (month) da yr (F4.0).
execute.
* concatentate date elements as strings.
string Period_String (a30).
compute Period_String = concat(ltrim(string(mo,month)), " ", ltrim(string(da,F4)), ", ", ltrim(string(yr,F4))).
execute.
see the revised month format (month9 instead of month):
compute Period_String = concat(ltrim(string(mo,month9)), " ", ltrim(string(da,F4)), ", ", ltrim(string(yr,F4))).
EDIT:
using #mirirai's one-liner suggestion + getting only first letter in capitals:
string Period_String(a20).
COMPUTE Period_String = CONCAT(
RTRIM(char.substr(STRING(period,MONTH9),1,1)),
RTRIM(lower(char.substr(STRING(period,MONTH9),2)))," ",
LTRIM(STRING(XDATE.MDAY(Period),F2)), ", ",
LTRIM(STRING(XDATE.YEAR(period),F4))
).

Lua Date Difference

I want to know if you can get the date difference of two dates that are predefined or dynamic in a long run.
Do you need a proper date format when using this function?
function datediff(d1, d2, ...)
col_date1 = os.time({year = d1:year(), month = d1:month(), day = d1:day() , hour = d1:hour(), min = d1:minute(), sec = d1:second() })
col_date2 = os.time({year = d2:year(), month = d2:month(), day = d2:day() , hour = d2:hour(), min = d2:minute(), sec = d2:second() })
local arg={...}
if arg[1] ~= nil then
if arg[1] == "min" then
return math.abs((col_date1 - col_date2) / 60)
elseif arg[1] == "hour" then
return math.abs((col_date1 - col_date2) / 3600)
elseif arg[1] == "day" then
return math.abs((col_date1 - col_date2) / 86400)
end
end
return math.abs(col_date1 - col_date2)
--return 0
end
This is the code. But I have no idea how this work exactly.
The input should be like 31122017 - 31122016 is 1 year. or something like that.
This code takes custom date objects as input. So, for example, if you had a date object d that represented a date like 2017-05-22, then calling d:year() would give you the number 2017, d:hour() would give you the number 5, etc.
There are no functions to make objects like this in standard Lua, so the project this code is in must be using a separate date library. You need to find out how to create the date objects that your project expects, and then pass those into the function.

Timestamp pattern

Let's assume I have the following reminder timestamp
local reminder_timestamp = "2013-12-13T00:00:00+01:00"
And I'm using the below function to return time in UTC
local function makeTimeStamp(dateString)
local pattern = "(%d+)%-(%d+)%-(%d+)%a(%d+)%:(%d+)%:([%d%.]+)([Z%p])(%d%d)%:?(%d%d)"
local year, month, day, hour, minute, seconds, tzoffset, offsethour, offsetmin = dateString:match(pattern)
local timestamp = os.time( {year=year, month=month, day=day, hour=hour, min=minute, sec=seconds} )
local offset = 0
if ( tzoffset ) then
if ( tzoffset == "+" or tzoffset == "-" ) then -- we have a timezone!
offset = offsethour * 60 + offsetmin
if ( tzoffset == "-" ) then
offset = offset * -1
end
timestamp = timestamp + offset
end
end
return timestamp
end
What should be the pattern above to match the reminder timestamp I mentioned earlier?
You need to use Lua's string parsing capabilities. Try a few of the techniques mentioned in the following, and if you still have issues, post specifically what is not working:
Question about splitting string and saving in several variables
Question about extracting data from a string, very similar to yours (although problem domain is GPS coordinates instead of date/time)
Question about how to do pattern matching in Lua, several good examples and links to docs
Here is the answer and the function actually works fine
pattern = "(%d+)%-(%d+)%-(%d+)%a(%d+)%:(%d+)%:([%d%.]+)([Z%p])(%d%d)%:?(%d%d)"
reminder_timestamp = "2013-12-23T08:00:00+01:00"
local year, month, day, hour, minute, seconds, tzoffset, offsethour, offsetmin = reminder_timestamp:match(pattern)
Resource: http://www.lua.org/manual/5.1/manual.html#5.4.1

Lua seconds format questions

I have this function:
function SecondsFormat(X)
if X <= 0 then return "" end
local t ={}
local ndays = string.format("%02.f",math.floor(X / 86400))
if tonumber(ndays) > 0 then table.insert(t,ndays.."d ") end
local nHours = string.format("%02.f",math.floor((X/3600) -(ndays*24)))
if tonumber(nHours) > 0 then table.insert(t,nHours.."h ") end
local nMins = string.format("%02.f",math.floor((X/60) - (ndays * 1440) - (nHours*60)))
if tonumber(nMins) > 0 then table.insert(t,nMins.."m ") end
local nSecs = string.format("%02.f", math.fmod(X, 60));
if tonumber(nSecs) > 0 then table.insert(t,nSecs.."s") end
return table.concat(t)
end
I would like to add weeks and months to it but cant get my head around the month part to move on to the week part just because the days in a month aren't always the same so can anyone offer some help?
The second question is, is using a table to store the results the most efficient way of dealing with this given the function will be called every 3 seconds for up to 100 items (in a grid)?
Edit:
function ADownload.ETA(Size,Done,Tranrate) --all in bytes
if Size == nil then return "--" end
if Done == nil then return "--" end
if Tranrate == nil then return "--" end
local RemS = (Size - Done) / Tranrate
local RemS = tonumber(RemS)
if RemS <= 0 or RemS == nil or RemS > 63072000 then return "--" end
local date = os.date("%c",RemS)
if date == nil then return "--" end
local month, day, year, hour, minute, second = date:match("(%d+)/(%d+)/(%d+) (%d+): (%d+):(%d+)")
month = month - 1
day = day - 1
year = year - 70
if tonumber(year) > 0 then
return string.format("%dy %dm %dd %dh %dm %ds", year, month, day, hour, minute, second)
elseif tonumber(month) > 0 then
return string.format("%dm %dd %dh %dm %ds",month, day, hour, minute, second)
elseif tonumber(day) > 0 then
return string.format("%dd %dh %dm %ds",day, hour, minute, second)
elseif tonumber(hour) > 0 then
return string.format("%dh %dm %ds",hour, minute, second)
elseif tonumber(minute) > 0 then
return string.format("%dm %ds",minute, second)
else
return string.format("%ds",second)
end
end
I merged the function into the main function as I figured it would probably be quicker but I now have two questions:
1: I had to add
if date == nil then return "--" end
because it errors occasionally with date:match trying to compare with "nil" however os.date mentions nothing in the literature about returning nil as its a string or a table so although the extra line of code fixes the issue I'm wondering why that behaviour occurs as I'm sure I caught all the non events in the previous returns?
2: Sometimes I see functions written like myfunction(...) and I'm sure that just does away with the arguments and if so is there a one line of code that could do away with the first 3 "if" statements?
You can use the os.date function to get date values in a useable format. The '*t' formating parameter makes the returned date into a table instead of a string.
local t = os.date('*t')
print(t.year, t.month, t.day, t.hour, t.min, t.sec)
print(t.wday, t.yday)
os.data uses the current time by default, you can pass it an explicit time if you want (see the os.data docs for more info on this)
local t = os.date('*t', x)
As for table performance, I wouldn't worry about that. Not only is your function not called all that often, but table handling is much cheaper than other things you might be doing (calling os.date, lots of string formatting, etc)
Why not let Lua's os library do the hard work for you?
There is probably an easier (read: better) way to figure out the difference to 01/01/70, but here is a quick idea of how you could use it:
function SecondsFormat(X)
if X <= 0 then return "" end
local date = os.date("%c", X) -- will give something like "01/03/70 03:40:00"
local inPattern = "(%d+)/(%d+)/(%d+) (%d+):(%d+):(%d+)"
local outPattern = "%dy %dm %dd %dh %dm %ds"
local month, day, year, hour, minute, second = date:match(inPattern)
month = month - 1
day = day - 1
year = year - 70
return string.format(outPattern, year, month, day, hour, minute, second)
end
I think that this should also be a lot quicker than constructing the table and calling string.format multiple times - but you'd have to profile that.
EDIT: I ran a quick test with two functions that concatenate "abc", "def" and "ghi" using both methods. Inserting those strings into a table an concatenating took 14 seconds (for several million runs of course) and using a single string.format() took 6 seconds. This does not take into account, that your code calls string.format() anyway (multiple times) - nor the difference between you figuring out the values by division and I by pattern matching. Pattern matching is certainly slower, but I doubt that it outweighs the gains from not having a table - and it's certainly convenient to be able to leverage os.time(). The fastest way would probably be figuring out the month and day manually and then using a single string.format(). But again - you'd have to profile that.
EDIT2: missingno has a good point with using the "*t" option with os.date to give you the values separately in the first place. Again, this depends on whether you want to have a table for convenience vs. a string for storage or whatever reasons. Combining "*t" and a single string.format:
function SecondsFormat(X)
if X <= 0 then return "" end
local date = os.date("*t", X) -- will give you a table
local outPattern = "%dy %dm %dd %dh %dm %ds"
date.month = date.month - 1
date.day = date.day - 1
date.year = date.year - 70
return string.format(outPattern, date.year, date.month, date.day, date.hour, date.min, date.sec)
end

Resources