Rounding months to the correct year - powerbi

I am creating an Age Dimension.
Granularity is months, so i have started by creating a column called TotalMonths, between 1 - 1440, which equates to 120 years.
I now want to add a year column.
I thought totalMonths/12 would work, but on month 6, the year rounds up to 1.
The year should only round up after 12.
Is there a way to do this in dax?

If you want to make a custom column in Power Query, then you can use Number.RoundDown function:
Year_M = Number.RoundDown([TotalMonths] / 12)
If you do it in DAX, then use ROUNDDOWN function:
Year_DAX = ROUNDDOWN(Age[TotalMonths] / 12, 0)
If you want first Year=1 to be for TotalMonth=13 instead, then subtract 1 from TotalMonth in the above calculations:
Year_M = Number.RoundDown(([TotalMonths] - 1) / 12)
Year_DAX = ROUNDDOWN((Age[TotalMonths] - 1) / 12, 0)

Related

How do I assimilate the division of wages per hour between permanent employee and intern in Dax?

I'm trying to do it with IF, but it gives a syntax error.
Below is the measurement.
sal hour =
[salary per day]/8
IF(SELECTEDVALUE('RH[office]) = "Internship" / 6
Your IF function is not correct
The function is
IF (<Logical Test>, <Result if true> , <Result if false>)
Using my example:
Selected Value Check = [Hours] / IF(SELECTEDVALUE('Table'[Column2]) = "A", 6, 8)
You need to check IF it is internship is true, then return 6 else return 8
sal hour = [salary per day] / IF(SELECTEDVALUE('RH[office]) = "Internship", 6, 8)
You should use the DIVIDE function as well, as it will handle divide by zero.

Power BI dividing function shows negative value instead of positive

I have a problem and probably it is very simple. There are sales values of 2 years for some markets in my data. I'm trying to calculate annual growths so I divide 2019 value of a market by 2018 value and then subtract -1. (Example: 2018 sales: $100, 2019 sales: $200. Growth is [(200/100)-1]= 1= %100) But some markets were 0 in 2018 and started to operate in 2019. Therefore, the growth must be +%100. But it gives -%100.
YTD19vs18 = (DIVIDE(SUM(YTDPerformans[YTD 2019]);SUM(YTDPerformans[YTD 2018])))-1
Sure it gives -1 because thats the result of the calculation
(0 / 200) - 1 = -1
You can include a check for this case. Somthing like if the previous year is zero return always 1 = 100%:
YTD19vs18 = IIF(
YTDPerformans[YTD 2018] = 0;
1;
DIVIDE(SUM(YTDPerformans[YTD 2019]);
SUM(YTDPerformans[YTD 2018]))
)-1
)

Find the date given the year, the month and the "nth" occurrance of day within the month C/C++

In order that a device (with limited memory) is able to manage its own timezone and daylight savings, I'm trying to calculate daylight savings triggers for 85 time zones based on a simplified description of each timezone. I have access to minimal C and C++ libraries within the device. The format of the timezone (inc. DST) description for each time zone is as follows:
UTC - the base time and date from system clock
GMTOffsetMinutes - offset from GMT with DST inactive
DSTDeltaMinutes - modifier to above with DST active (as applicable to TZ)
DSTStartMonth - month in which DST becomes active
DSTStartNthOccurranceOfDay - the nth occurrence of the day name in month
DSTDayOfWeek - Sun = 0 through to Sat = 6
DSTStartHour - hour at which DST becomes active
DSTStartMinute - minute at which DST becomes active
and corresponding EndMonth, EndNth..., EndHour, EndMinute
I have found numerous examples going the other way, i.e. starting with the date, but they involve using the modulus, keeping the remainder and dropping the quotient hence I have been unable to transpose the formula to suit my needs.
I also tried to reuse the standard "Jan = 6, Feb = 2, Mar = 2, Apr = 5, May = 0, etc. modifier table and year modifiers from the "tell me what day the 25th of June, 2067 is?" party trick and developed the following algorithm.
Date = DayOfWeek + ((NthOccuranceOfDay - 1) x 7 ) - MonthCode - YearCode
This worked for the first 6 random test dates I selected but then I started to see dates for which it failed. Is it possible that the basic algorithm is sound but I'm missing a further modifier or maybe that I'm applying the modifiers incorrectly?
Is there another solution I could utilize?
Using this open source, cross platform date library, one can write:
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
year_month_day us_daylight_starts = sys_days(sun[2]/mar/2015);
year_month_day us_daylight_ends = sys_days(sun[1]/nov/2015);
std::cout << us_daylight_starts << '\n';
std::cout << us_daylight_ends << '\n';
}
which will output:
2015-03-08
2015-11-01
The formulas this library is based on are in the public domain and documented here.
The algorithms paper has very complete unit tests validating the date algorithms over a range of millions of years (a far larger range than is necessary).
Sometimes daylight savings rules are written in terms of the last weekday of a month. That is just as easily handled:
year_month_day ymd = sys_days(sun[last]/nov/2015);
std::cout << ymd << '\n'; // 2015-11-29
That formula will be off by one week (or even two weeks) if MonthCode + YearCode is greater than or equal to DayOfWeek, because in that case you will be counting NthOccurenceOfDay from a negative date.
As an alternative, with no tables, you can compute the day of week of the first of the month using, for example, Zeller's algorithm:
int NthOccurrence(int year, int month, int n, int dayOfWeek) {
// year is the current year (eg. 2015)
// month is the target month (January == 1...December == 12)
// Finds the date of the nth dayOfWeek (Sun == 0...Sat == 6)
// Adjust month and year
if (month < 3) { --year, month += 12; }
// The gregorian calendar is a 400-year cycle
year = year % 400;
// There are no leap years in years 100, 200 and 300 of the cycle.
int century = year / 100;
int leaps = year / 4 - century;
// A normal year is 52 weeks and 1 day, so the calendar advances one day.
// In a leap year, it advances two days.
int advances = year + leaps;
// This is either magic or carefully contrived,
// depending on how you look at it:
int month_offset = (13 * (month + 1)) / 5;
// From which, we can compute the day of week of the first of the month:
int first = (month_offset + advances) % 7;
// If the dayOfWeek we're looking for is at least the day we just
// computed, we just add the difference. Otherwise, we need to add 7.
// Then we just add the desired number of weeks.
int offset = dayOfWeek - first;
if (offset < 0) offset += 7;
return 1 + offset + (n - 1) * 7;
}

How do i correctly add days to given date?

I made this operator for class where I store date, it is supposed to add given number of days to date and convert it back to human format
CDate CDate::operator+(const int x)
{
time_t t;
struct tm tmp = {0};
struct tm newtime = {0};
tmp.tm_year = timeinfo.tm_year;
tmp.tm_mon = timeinfo.tm_mon;
tmp.tm_mday = timeinfo.tm_mday + x;
t = mktime(&tmp);
newtime = *(localtime(&t));
return CDate(newtime.tm_year,newtime.tm_mon,newtime.tm_mday);
}
problem is it compute date 3 days higher that it should
concrete problem is, I have date 2000-01-02 (year-month-day) and i try to add 1500 days, expected result is 2004-02-10 but I am getting 2004-02-13
check
what am I doing wrong here?
my code:
http://pastebin.com/wLxzTe3W
You have two errors.
First, the tm passed to mktime is invalid: The year shouldn´t be the absolute year like 2000, but the year difference from 1900, ie. 100 for 2000. With this problem corrected, I get 2004-02-12 as result (neither 2004-02-13 nor 2004-02-10).
(On my computer, the program (without any changes) just crashes: mktime returns -1, localtime can´t handle it and returns an invalid pointer, which is used in the same line...)
Second, in the same struct, the day may be 1-31, but the month only 0-11 (not 1-12). Your 2000-01-02 is the second day of February, not January.
Knowing this, the result is correct (I´ll write the full year, but month starting from 0):
1500 days to add to 2000-01-02:
2000 has 366 days (leap year), and we don´t need January and the first February day:
2000-01-02 + (366-31-1) days = 2001-00-01, 1166 days to add left
Another 365 days makes 2002-00-01, 801 days to add left
Another 365 days makes 2003-00-01, 436 days to add left
Another 365 days makes 2004-00-01, 71 days to add left
Another 31 of January makes 2004-01-01, 40 days to add left
Another 29 of leap February makes 2004-02-01, 11 days to add left
Another 11 added makes 2004-02-12
Read http://www.cplusplus.com/reference/ctime/tm/ carefully
This is the algorithm for adding days to the date.
Calculate day number from date.
function g(y,m,d)
m = (m + 9) % 12
y = y - m/10
return 365*y + y/4 - y/100 + y/400 + (m*306 + 5)/10 + ( d - 1 )
To add no. of days in the date->
g(y2,m2,d2) + no_of_days
After this, you can convert your days back to date.
function d(g)
y = (10000*g + 14780)/3652425
ddd = g - (365*y + y/4 - y/100 + y/400)
if (ddd < 0) then
y = y - 1
ddd = g - (365*y + y/4 - y/100 + y/400)
endif
mi = (100*ddd + 52)/3060
mm = (mi + 2)%12 + 1
y = y + (mi + 2)/12
dd = ddd - (mi*306 + 5)/10 + 1
return y, mm, dd

Determine time period since event (up to n leads/lags)

I want to measure the number of periods (here years) since an event occurred (here represented by indicator variable pos) up to a given number of leads and lags (here three).
The following code works, but seems hackish and like I'm missing something fundamental. Is there a more robust solution that takes advantage of built in functions or a better logic? I'm on 11.2. Thanks!
version 11.2
clear
* generate annual data
set obs 40
generate country = cond(_n <= 20, "USA", "UK")
bysort country: generate year = 1766 + _n
generate pos = 1 if (year == 1776)
* generate years since event (up to three)
encode country, generate(countryn)
xtset countryn year
generate time_to_pos = 0 if (pos == 1)
forvalues i = 1/3 {
replace time_to_pos = `i' if (l`i'.pos == 1)
replace time_to_pos = -1 * `i' if (f`i'.pos == 1)
}
Clear question.
This can be shortened. Here is one way. Starting with your code to set up a sandpit
version 11.2
clear
* generate annual data
set obs 40
generate country = cond(_n <= 20, "USA", "UK")
bysort country: generate year = 1766 + _n
Now it is
gen time_to_pos = year - 1776 if abs(1776 - year) <= 3
That is all that seems needed for your example. If you want to generalise to multiple events within each panel, I'd like to know the rules for such events.
I was going to show a trick from http://www.stata-journal.com/article.html?article=dm0055 but it doesn't appear needed.