Power BI Desktop
Version: 2.73.5586.984 64-bit (September 2019)
I am creating a calculated column to determine if a ticket has been completed in a "Current" or "Backlog" state. Our reporting period month goes from the 26th of the month to the 25th. If a ticket was completed in the reporting period m/26 - m/25 it would be considered "Current." If the ticket was completed outside of that time frame then it would be "Backlog." Also, if the current ticket has not been completed but still has the possibility of being completed in the same reporting period then that would be listed as "Current", but if it goes on to the next reporting month then it would be "Backlog."
Example:
Created 1/1/2021 & Completed 1/10/2021 = Current
Created 1/1/2021 & Completed 3/18/2021 = Backlog
Created 1/25/2021 & Completed 1/26/2021 = Backlog
Created 4/20/2021 & Not Completed & Today [4/30/2021] = Backlog
Created 4/29/2021 & Not Completed & Today [4/30/2021] = Current
I have written the following DAX to handle this but I seem to run into issues after the end/at the start of the reporting period, where the calculations don't work properly and everything lists as either current or backlog.
I also have a helper column in my Date Table that determines what the current reporting period is based on the current day, but I am not using it in this formula, but can if it would make it more efficient.
What is a better/proper way to do this?
Current/Backlog Caluclated Column:
Current_Backlog =
VAR CreatedDay = Day(IR_SR[Created_Date])
VAR CompletedDay = Day(IR_SR[Completed_Date])
VAR CreatedMonth = Month(IR_SR[Created_Date])
VAR CompletedMonth = Month(IR_SR[Completed_Date])
VAR CreatedMonthAdd = Month(IR_SR[Created_Date])+1
VAR CompletedMonthAdd = Month(IR_SR[Completed_Date])+1
VAR CurrentMonth = Month(TODAY())
VAR CurrentMonthAdd = Month(TODAY())+1
VAR CurrentDay = Day(TODAY())
RETURN
//If the date the ticket was completed is before the 26th and the created and completed month match, mark as current
IF(CompletedDay < 26 && CreatedMonth = CompletedMonth, "Current",
//If the completed date is after or equal to the 26th see if the created month plus one and completed month plus one match, mark as current
IF(CreatedDay >= 26 && CompletedDay >= 26 && CreatedMonthAdd = CompletedMonthAdd, "Current",
//If the completed date is after or equal to the 26th and the created date is after or equal to the 26th see if the created and completed month plus one match, mark as current
IF(CreatedDay >= 26 && CreatedMonthAdd = CompletedMonth, "Current",
//If the ticket is not completed and the created date is less then the 26th and the created month and current month match, mark as current
IF(IR_SR[Open/Closed] = "Open" && CurrentDay < 26 && CreatedDay < 26 && CreatedMonth = CurrentMonth, "Current",
//If the ticket is not completed and the created date is greater then the 26th and the created month and current month match plus one, mark as current
IF(IR_SR[Open/Closed] = "Open" && CurrentDay >= 26 && CurrentDay < 1 && CreatedDay >= 26 && CreatedMonthAdd = CurrentMonthAdd, "Current",
IF(IR_SR[Open/Closed] = "Open" && CurrentDay < 26 && CurrentDay >= 1 && CreatedDay >= 26 && CreatedMonthAdd = CurrentMonth, "Current",
"Backlog"))))))
Current Reporting Month:
= Table.AddColumn(#"Inserted Day Name", "Reporting_Period", each if Date.Day([Date]) >= 26
then Date.StartOfMonth(Date.AddMonths([Date], 1))
else Date.StartOfMonth([Date]))
an advice in this case. Compare both DAX formula in the performance analyizer inside Power BI and check how much time spent the calculation.
I guess all your data are imported, in this case data are cached, so first problem about performance is solved.
Anyway, paste second part of your DAX code and I'll check it.
Thanks
Related
For example the date range is
28-01-2022 and 20-03-2022
I want to count separately the days that belong to january (3) february (27) and march (19)
I would really appreciate the help!!
In python, you can do the following:
import calendar
import datetime
from dateutil import relativedelta
start_str = "1-03-2022"
end_str = "20-12-2024"
start = datetime.datetime.strptime(start_str, "%d-%m-%Y")
end = datetime.datetime.strptime(end_str, "%d-%m-%Y")
days = []
while start.year <= end.year and start.month <= end.month:
if start.year == end.year and start.month == end.month:
days.append(end.day - start.day)
else:
days.append(calendar.monthrange(
start.year, start.month)[1]-start.day+1)
start = start.replace(day=1)
start += relativedelta.relativedelta(months=1)
print(*days)
This includes the start day and excludes the end date, meaning that in your example, 4 days belong to January and 19 to March. Does February have 27 days only?
In Stata I am trying to assess which of the given birthdays is the next one compared with a given date. My data looks like this:
All dates are in daily format (%dD_m_Y), e.g. 18mar1926
Variable date which is the reference date with which all other dates should be compared
Variables birth1, birth2, birth3, birth4, birth5, birth6 contain the birthday of all possible household members.
For example: A household with two adults A and B. The birthday of A is 20th Nov 1977 and the birthday of person B is 30th March 1978. The reference date is 29.11.2020. I want to know who is the person who has the next birthday, in the example above it is person B, because person A has had its birthday one week before the reference date, so the next birthday in this household will be celebrated on the 30 March 2021.
Example data:
date
birth1
birth2
birth3
birth4
birth5
birth6
02feb2021
15jan1974
27nov1985
30nov2020
31aug1945
27jun1999
07apr1997
19nov2020
27sep1993
30dec1996
29jan2021
29mar1973
05dec2020
21jan1976
02oct1976
21jan1976
25may1995
15feb1997
25nov2020
25nov1943
29nov1946
02feb2021
28apr1979
EDITED to account for Feb 29
*The edit will treat people who have a February 29 birthday as if it were March 1 in cases when the year of date is not a leap year. If that doesn't make sense for your particular use case, it should be easy to alter the code below as you see fit.
Since you want the next birthday in the year rather than the closest birthday, you can use the year of date and the month and day from birth{i} to create a date for each person's next birthday. Then you can sinmply take the earliest value from each household. I reshape long, and generate a person and household id in order to do this.
Make example data
clear
set obs 6
set seed 1996
generate date = floor((mdy(12,31,2020)-mdy(12,1,2015)+1)*runiform() + mdy(12,1,2015))
format date %td
forvalue i = 1/6 {
gen birth`i' = floor((mdy(12,31,1996)-mdy(12,1,1980)+1)*runiform() + mdy(12,1,1980)) if _n < `i' == 0
format birth`i' %td
}
replace birth6 = birth4 in 6 // want a tie
replace birth2 = date("29feb1996","DMY") in 3 // Feb 29
Find Next Birthday
gen household_id = _n
reshape long birth, i(date household_id) j(person)
drop if mi(birth)
gen person_next_birthday = mdy( month(birth), day(birth), year(date))
* TREAT FEB 29 as if they have a march 1 birthday in non-leap years
replace person_next_birthday = mdy(3,1,year(date)) if month(birth) == 2 ///
& day(birth) == 29 & mod(year(date),4)!=0
replace person_next_birthday = mdy( month(birth), day(birth), year(date) + 1) if person_next_birthday < date
replace person_next_birthday = mdy(3,1,year(date)+1) if month(birth) == 2 ///
& day(birth) == 29 & mod(year(date) + 1,4)!=0 & person_next_birthday < date
format person_next_birthday %td
bysort household_id (person_next_birthday): gen next_bday = person_next_birthday[1]
format next_bday %td
drop person_next_birthday
reshape wide birth, i(date household_id next_bday) j(person)
gen next_bday_persons = ""
* Make a string to present household persons who have next bday
foreach v of varlist birth* {
local person = subinstr("`v'","birth","",.)
local condition = "month(`v') == month(next_bday) & day(`v') == day(next_bday)"
local condition_feb29 = "month(next_bday) == 3 & day(next_bday) == 1 & month(`v') == 2 & day(`v') == 29"
replace next_bday_persons = next_bday_persons + "|`person'" if `condition' | `condition_feb29'
}
replace next_bday_persons = regexr(next_bday_persons,"^\|","")
order next_bday_persons, after(next_bday)
The last loop is unnecessary, but illustrates that this is robust to ties.
This question already has answers here:
Calculate days to go until a particular date with momentjs
(3 answers)
Closed 1 year ago.
I want to validate if the following date is valid : 30 Feb 2021.
So the main issue is 30 Feb 2021 shouldn't be a valid date or 31 April 2021. is it possible to achieve that with moment js or luxon? or should i use another approach?
let m = moment([2021, 2, 31]);
console.log("Date is valid", m.isValid()); \\returns true which is not a valid date!
I don't know moment.js or luxon , but it's achievable in basic JS (although a little long-winded)
JavaScript will up-tick the date, so the 29th of Feb is the 1st of March.
Therefore we can compare the before and after version :
var month = 1; // zero based - 1 is feb
var day = 30;
var year = 2021;
var testDate = new Date(year, month, day); // will convert to 2nd of March
var parsedDate = testDate.getDate(); // will be 2
var parsedMonth = testdate.getMonth() // will be 2 , zero based, March
var parsedYear = testDate.getFullYear(); // remains 2021 in this case
var isValidDate = parsedDate === day && parsedMonth === month && parsedYear === year;
This could be condensed a lot but I've made it as bloated as possible for readability
you could easily turn it into a function, something like this (untested)
function IsValidDate(year, month, day){
var InputMonthsAreOneBased = 0; // change to 1 if needed
var testDate = new Date(year, month - InputMonthsAreOneBased, day );
return testDate.getDate() === day && testdate.getMonth() === (month - InputMonthsAreOneBased) && testDate.getFullYear() === year;
}
I'm trying to build my first app using flutter framework. The app is about my "End of Year Challenge". It started from 1st Sept 2019 and will last till the end of this year.
What I'm trying to achieve is - I want to display the current day number of the challenge period. eg: 1st Sept is Day 1, 30th Sept is Day 30 and 1st Oct is Day 31 and so on.
I'm trying to get the first day of Sept and assign it to 1. Then using a loop I want the app to update the day to the current day. The loop will stop once the current day equals to 122 (as this would be the last day of the challenge)
Here's the screenshot of the UI
final firstSeptember = DateTime.utc(2019, DateTime.september, 1);
static const totalNumberOfDays = 122;
int noOfDay(){
int dayOne = firstSeptember.day; // I'm just trying codes, IDK the actual code/business logic
return dayOne;
}
In function you'd use
int noOfDay(){
var todayDate = DateTime.now();
final firstSeptember = DateTime.utc(2019, DateTime.september, 1);
var difference = todayDate.difference(firstSeptember);
return difference.inDays + 1;
}
Explanation:
Get today's date
var todayDate = DateTime.now();
You already have start date which is
final firstSeptember = DateTime.utc(2019, DateTime.september, 1);
All you need to do is subtraction.
var difference = todayDate.difference(firstSeptember);
int daysCompleted = difference.inDays + 1;
What I am trying to do here is this - I want to give index to only the workdays in each week.
So, if in a week, Monday and Wednesday are holidays, then Tuesday should get 1, Thursday should get 2, Friday should get the index 3. Otherwise, in a normal week without any holidays, Monday should get 1, Tuesday 2, Wednesday 3, and so on ...
Here is the code I have written (I haven't coded in years now, so please pardon the crude approach)
Sheet 'Holidays' contains a list of holidays in the column B starting from row 2
Variable date is the date for which I want to find out the index for
Variable dayOfTheWeek is the number of day of 'date' counted from last Sunday, so if date is a Monday, dayOfTheWeek is 1; if date is Tuesday, dayOfTheWeek is 2, and so on ...
function indexOfWorkdayOfTheWeek (date, dayOfTheWeek, lastSundayDate)
{
var activeSheet = SpreadsheetApp.getActiveSpreadsheet();
var activeCell = activeSheet.getActiveRange();
var activeRow = activeCell.getRowIndex();
var activeColumn = activeCell.getColumn();
var count = 1;
for (var j = 1; j < dayOfTheWeek; j++)
{
var date2 = lastSundayDate.valueOf() + j*86400;
Logger.log('Date ' + j + ' is:' + date2);
Logger.log('Last Sunday is:' + lastSundayDate);
if (holidayOrNot(date2) == true)
{
}
else
{
count = count + 1;
}
}
return count;
}
function holidayOrNot(date2)
{
var holidaysSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Holidays');
var listOfHolidays = holidaysSheet.getSheetValues(2, 2, 95, 1);
var isDateMatch = false;
for (var k = 0; k < 90; k++)
{
if (date2 == listOfHolidays[k].valueOf())
{
isDateMatch = true;
break;
}
else
{
continue;
}
}
return isDateMatch;
}
I think the problem is two-fold here:
The date2 calculation isn't working for some reason (var date2 = lastSundayDate.valueOf() + j*86400;)
The function holidayOrNot is returning false, no matter what, even if it encounters a holiday ... the condition date2 == listOfHolidays[k] isn't working for some reason...
Help would be appreciated!
maybe this method below could help you in your calculations, it returns an integer corresponding to the day of the year so if you apply this to your holidays days and compare to the days of interest it could be a good way to find matches.
here it is, just add these lines outside of any function in your script (so you can use it anywhere) then use it like this :
var d = new Date().getDOY();
Logger.log(d)
Here the method :
Date.prototype.getDOY = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((this - onejan) / 86400000);
}
Assuming that lastSundayDate is being passed around correctly, I see a glaring problem:
lastSundayDate.valueOf().
valueOf() on Date objects returns the primitive value... it looks like you're going for adding a day to the date (86400 seconds * j)? I can't tell what the logic is supposed to be here. But the valueOf() date2 is definitely giving you an integer something like: 1384628769399 (see here).
What you really want to accomplish is something like Date.getDay(), or something similar so that you can add hours, days, etc. to the original Date. This is likely the source of all your problems.
What you can do is read the Mozilla Developer Network documentation on Date objects to see all of the functions on Dates and their uses. You can greatly simplify what you're trying to do by using these functions, instead of doing abstract operations like j * 86400.
It should also be noted that you can do simple operations such as the following, to add 4 hours to the current Date (time):
var myDate = new Date();
Logger.log(myDate); // ~ console.write
var laterDate = new Date(myDate.setHours(myDate.getHours() + 4));
Logger.log(laterDate); // ~ console.write
which gives the following:
[13-11-16 14:13:38:947 EST] Sat Nov 16 14:13:38 GMT-05:00 2013
[13-11-16 14:13:38:954 EST] Sat Nov 16 18:13:38 GMT-05:00 2013
Working with dates can be tricky - but it's always best to use the simplest methods that are available, which are built into the Date objects themselves. There are also numerous other libraries that provide extended functionality for Dates such as Date js.
If you're still running into your problem after attempting to try using methods I displayed above, please run your script and post both the Execution Transcript and the content of the Logger so that I can help you narrow down the issue :)