Calculating Age in X++ - x++

I am trying to calculate an age in x++ where the customer is born on 1/6/2010 to the selected day of his visit - 1/6/2023 today but the result doesn't give me 13 years old but gives me 12.
real ageDiffReal;
int ageDiffInt;
date datetoday = DateTimeUtil::date(Visitas.RFC_DataVisita);
ageDiffReal = (datetoday - mkDate(dir.BirthDay,dir.BirthMonth,dir.BirthYear)) / 365.242199;
ageDiffInt = Round(ageDiffReal,0);
info(strFmt('%1,%2',ageDiffReal, ageDiffInt));
I tried with / 365 and with 365.25 because of leap years but still didn't work well

You're using round(...) incorrectly.
ageDiffInt = decRound(ageDiffReal, 0); // Better
ageDiffInt = round(ageDiffReal, 1); // Works too
round(...) - The number that is a multiple of the value specified by the _decimals parameter and is closest to the value specified by the _arg parameter.
See https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-ref/xpp-math-run-time-functions

Related

Qlikview Format textbox expression as percentage to 3 decimal places

I am trying to show percentage increase / decrease based on week number for 2018 v 2019 with an expression in a textbox in Qlikview: Here is my expression:
= num(Sum({<Year = {$(=Max(Year))},
Week = {"$(=Week(Today()))"}>}Retail) - Sum({<Year = {$(=Max(Year)-1)},
Week = {"$(=Week(Today()))"}>}Retail)) / num(Sum({<Year = {$(=Max(Year)-1)},
Week = {"$(=Week(Today()))"}>}Retail),'##0 %')
No matter what i try i end up with -0.38877082 etc.
What am i doing wrong?
Please fix parenthesis and formatting:
= num(Sum({}Retail) - Sum({}Retail) / Sum({}Retail),'##,#0.00 %')

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

constraints inlist for integer

I need to write a constraint for credit card expiry year in the constraints
This is my constraints
static constraints = {
cardNumber(nullable:false, blank:false, creditCard:true)
expiryMonth(nullable:false, range:1..12)
expiryYear(nullable:false, range:(defaultExpiryYear)..(defaultExpiryYear + YEARS_TO_LIST))
}
where defaultExpiryYear = Current Year - 2000
and YEARS_TO_LIST = 10 years.
But this case will fail if the year is 2095 because the range will go expiryYear(nullable:false, range:95..105)
but as the expiryYear is only 2 digit for the year 2105 it will give 05 and it will fail.
How do I convert it into get in inlist for the range?
I could be wrong but from my point of view, you should not worry about things that are about 90 years in the future. in 90 years - who could guarantee that there are still credit cards? if there are still credit cards, will they have an "expiry year"? if they'll have an expiry date, how is it calculated?
so, sorry that this may not be the answer you expected, but given the speed of development of the past few years I would not worry about your problem in any way ;)
This is how i fix it please comment if you have any other good ideas
where epiryStartYear and expiryEndYear are 4 digits year
expiryYear(nullable:false, InList:( getExpiryRangeList()))
def static private getExpiryRangeList() {
def yearList = []
(expiryStartYear..expiryEndYear).each {
yearList << it % 100
}
yearList
}
OR i can do
def static private getExpiryRangeList() {
[expiryStartYear..expiryEndYear].collect(it % 100)
}

Creating running mean with missing values in Stata / SAS

I have a time series of hourly measurement of environmental and meteorological variables (temperature and humidity) over several years. From these hourly values I would like to calculate a 24 hour running mean to create exposure parameter. For this the requirement is that at least 17 of the hourly measurements should be available with no more than 6 hours of consecutive missing values. If more than 6 hourly values are consecutively missing in 24, the data for that specific date is set to missing. How can I implement this in Stata or SAS?
Thanks in advance
It looks like you can create a dummy variable for a "valid" observation using a combination of
by varname : generate ....,
egen, and
lag variables (L.varname, L2.varname... L24.varname...)
Then, create your average using the subset of your data (e.g., yourcommand ... if dummy==1 ...)
Ok here is my attempt. First create some sample data to use:
**
** CREATE ~3 YEARS DAYS OF HOURLY TEMPERATURE DATA
** THIS IS UGLY - IM SURE THERES A BETTER WAY TO DO IT BUT WHATEVER
*;
data tmp;
pi = constant('pi');
do year=1 to 3;
linear_trend = 0.1 * year;
day = 0;
do yearly_progress=0 to (pi*2) by (pi/182.5);
day = day + 1;
yearly_seasonality = (1 + sin(yearly_progress)) / 2;
hour = 0;
day_mod = (ranuni(0)*10);
do hourly_progress=0 to (pi*2) by (pi/12);
hourly_seasonality = (1 + sin(hourly_progress)) / 2;
if hour ne 24 then do;
temperature = 60*(1+linear_trend) + (20 * yearly_seasonality) + (30 * hourly_seasonality) - day_mod;
output;
end;
hour = hour + 1;
end;
end;
end;
run;
**
** ADD SOME MISSING VALS
** ~ 10% MISSING
** ~ 10 IN A ROW MISSING EVERY 700 OR SO HOURS
*;
data sample_data;
set tmp;
if (ranuni(0) < 0.1) or (mod(_n_,710) > 700) then do;
temperature = .;
end;
run;
Secondly calculate the moving average for temperature if the requirements are met:
**
** I DONT NORMALLY LIKE USING THE LAG FUNCTION BUT IN THIS CASE ITS IDEAL
*;
data results;
set sample_data;
**
** POPULATE AN ARRAY WITH THE 24 CURRENT VALUES
** BECAUSE WE ARE USING LAG FUNCTION MAKE SURE IT IS NOT WITHIN ANY
** CONDITIONAL IF STATEMENTS
*;
array arr [0:23] temperature0-temperature23;
temperature0 = lag0(temperature);
temperature1 = lag1(temperature);
temperature2 = lag2(temperature);
temperature3 = lag3(temperature);
temperature4 = lag4(temperature);
temperature5 = lag5(temperature);
temperature6 = lag6(temperature);
temperature7 = lag7(temperature);
temperature8 = lag8(temperature);
temperature9 = lag9(temperature);
temperature10 = lag10(temperature);
temperature11 = lag11(temperature);
temperature12 = lag12(temperature);
temperature13 = lag13(temperature);
temperature14 = lag14(temperature);
temperature15 = lag15(temperature);
temperature16 = lag16(temperature);
temperature17 = lag17(temperature);
temperature18 = lag18(temperature);
temperature19 = lag19(temperature);
temperature20 = lag20(temperature);
temperature21 = lag21(temperature);
temperature22 = lag22(temperature);
temperature23 = lag23(temperature);
**
** ITERATE OVER THE ARRAY VARIABLES TO MAKE SURE WE MEET THE REQUIREMENTS
*;
available_observations = 0;
missing_observations = 0;
max_consecutive_missing = 0;
tmp_consecutive_missing = 0;
do i=0 to 23;
if arr[i] eq . then do;
missing_observations = missing_observations + 1;
tmp_consecutive_missing = tmp_consecutive_missing + 1;
max_consecutive_missing = max(max_consecutive_missing, tmp_consecutive_missing);
end;
else do;
available_observations = available_observations + 1;
tmp_consecutive_missing = 0;
end;
end;
if tmp_consecutive_missing <= 6 and available_observations >= 17 then do;
moving_avg = mean(of temperature0-temperature23);
end;
run;
A Stata solution:
Use tssmooth ma myvar_ma = myvar, w(24) to create a moving average. Missings will be ignored.
Create an indicator gen ismiss = missing(myvar)
Use tssmooth ma ismiss_ma = ismiss, w(24) to create a moving average of the indicator.
replace myvar_ma = . if ismiss_ma > (7/24)
(At least 17/24 must be present, so 7 or fewer missing is acceptable, but 8 or more is not.
EDIT. tsegen from SSC now offers a simple approach to this kind of problem. You can specify the minimum acceptable number of non-missing values in the window directly in the command syntax.
For general moving average calculations, using PROC EXPAND is the easiest method (you need ETS licenced to use this procedure). For example, the code below will calculate a 24 period moving average and set the first 16 observations to missing. However, to comply with the rest of your criteria you would still need to run a data step afterwards, along the lines of Rob's code, so you may as well perform all the calculations within that step.
proc expand data=sample_data out=mov_avg_results;
convert temperature=mean_temp / method=none transformout=(movave 24 trimleft 17);
run;

Resources