How to get number of days between two dates in nodatime - nodatime

I need to compute the number of days between two dates using NodaTime, and to do it in a timezone.
The end time is date based with an implied time of midnight at the end of the day. This date is in a timezone.
The start time is the current time, but I am passing it into the function so that the function is testable.
I tried using Period, which seems like the obvious answer, but Period is too granular on one end (when we are on the end day) and not granular enough when we are more than 1 month away.
So if Now is July 9, 5:45pm in America/Toronto and the End Time is Sept 1, 00:00:00, then I would like to be able to calculate 54 days. (assuming I counted the number of days on my calendar correctly. :) )
I figured I would have to handle the sub day problem myself, but it surprised me when I had to figure out how to handle the greater than a month problem.
Is there an obvious way to get the number of days between two times from NodaTime? I have it down to three lines of code using .Net's DateTime and TimezoneInfo classes, but I want to move to NodaTime for all the reasons specified on the site.
Thanks

I should have read the Arithmetic section of the docs more closely before posting.
You can specify which unit you want the math result to be in with a 3rd parameter. Here is what I needed:
Period timeLeft = Period.Between(nowInTz.LocalDateTime, endDate, PeriodUnits.Days);
this is from the docs:
http://nodatime.org/unstable/userguide/arithmetic.html
Hope this helps somebody else in the future.

Related

Excel subtract X days from date and then find last specific workday date

here's my problem:
We have an Excel sheet at work in order to manage various tasks all set on individually specified timelines - we're talking hundreds of tasks per month with dates that are currently all being maintained manually.
Let's say we have Task A and that task has a Due Date. That Task is split into several subtasks, all with their individual due dates. Date 1 would then always be Due Date - 10 days, Date 2 would be Due Date - 20 days, Date 3 would be Due Date - 17 days and so on. This then creates a neat timeline of when everything needs to be done.
That in itself would be easy enough, problem is that all of these subtasks have to be done on a specific workday as well. Meaning that subtask 1 would not only have to be done Due Date - 10 days, but it would also have to fall on a Monday - if for whatever reason Due Date - 10 would happen to fall on like a Wednesday, it would have to subtract another 2 days. And then the real problem is that Date 2 and 3 each have to fall on different workdays and Task B has an entirely different schedule again.
Now, the first thing that came to my mind was attempting to just nest a couple IFs - and I've even managed to come up with a working formula for that. Problem here is that it's so stupidly long and (thanks Excel) utterly unreadable - if for some reason someone else had to change something about it or troubleshoot the entire file 1-2 years from now, they'd probably have to spend at least an hour reconstruct how the hell any of it actually worked. Which doesn't sound particularly appealing to us.
Here's a screenshot to help illustrating the situation:
And here's a draft of the current formula that I'm really not happy with, despite it somewhat doing the job:
=IF(AND(WEEKDAY(K2-VLOOKUP(B2,Table1,3,FALSE),11)>5,VLOOKUP(B2,Table1,5,FALSE)=0),(K2-VLOOKUP(B2,Table1,3,FALSE))-(WEEKDAY(K2-VLOOKUP(B2,Table1,3,FALSE),11)-5), IF(VLOOKUP(B2,Table1,5,FALSE)=0,K2-VLOOKUP(B2,Table1,3,FALSE), IF(WEEKDAY((K2-VLOOKUP(B2,Table1,3,FALSE)),11)=0,K2-VLOOKUP(B2,Table1,3,FALSE), (VLOOKUP(B2,Table1,5,FALSE)-WEEKDAY(K2-VLOOKUP(B2,Table1,3,FALSE),11))+K2-VLOOKUP(B2,Table1,3,FALSE))))
My question is now: Does anyone have an idea how to solve this in a less confusing and unclear manner? I was trying to get something done using =CHOOSE() but ultimately ended up with the same problem of eventually having to resort to 7 IFs and dozens of LOOKUPs, making the final formula just as long. I wouldn't be disinclined towards some kind of helper table that asigns the last 7 days and their workdays to every single day of the year... but I don't think tossing another 20,000 calculated cells into a file that already has tens of thousands other calculated cells would really be a serviceable alternative... or make the situation any less obscure at all tbh.
So, anyone any idea how to go about this? Or is there really no realistic alternative than to use a bunch of IFs?
Edit: Forgot to mention that 1 special case:
There's also the situation when a date doesn't have to fall on a specific workday - in which case it's simply due date - X days. The problem here is that in those cases the dates could fall on a weekend, so the formula would have to move these dates to the previous Friday as well.
Assume you have some date and you want to "back up" ten days and then to the preceding Monday, unless the resultant date is a Monday. The general formula would be something like:
=A2-10+1-WEEKDAY(A2-10-DOW)
Where DOW translates into
Sunday=0
Monday=1
Tuesday=2
...
You should be able to modify your formulas to use this algorithm for day of the week.
If the two tables are named thisTable and keyTable, the following 365 formula is one way of implementing:
If your tables are as below, you can enter the formula in B2 and fill down and across. The references should self-adjust and return the proper dates.
Note that in keyTable, I enter the day of the week DOW as defined above, and not the textual date.
=LET(dys,VLOOKUP(thisTable[#[Task]:[Task]],KeyTable,COLUMNS($A:A)*2,FALSE),
dow,VLOOKUP(thisTable[#[Task]:{Task]],KeyTable,COLUMNS($A:A)*2+1,FALSE),
due,thisTable[#[DueDate]:[DueDate]],
IF(dow="flexible",WORKDAY(due-dys+1,-1),due-dys+1-WEEKDAY(due-dys-dow)))
If you want to have the result be the closest workday, instead of the preceding workday, then you need to add two clauses to the LET function
Calculate the subsequent workday date
Then use an IF to return the closest one to the original target
eg:
=LET(dys,VLOOKUP(thisTable[#[Task]:[Task]],KeyTable,COLUMNS($A:A)*2,FALSE),
dow,VLOOKUP(thisTable[#[Task]:[Task]],KeyTable,COLUMNS($A:A)*2+1,FALSE),
due,thisTable[#[DueDate]:[DueDate]],
dayPrev,IF(dow="flexible",WORKDAY(due-dys+1,-1),due-dys+1-WEEKDAY(due-dys-dow)),
daySubseq,IF(dow="flexible",WORKDAY(due-dys+1,-1),due-dys+7-WEEKDAY(due-dys-1-dow)),
IF((daySubseq-due+dys)>3,dayPrev,daySubseq))

Spotfire: Convert string date to datetime

I have a feeling this is easy but I just can't crack it and am spending too much time on it. I am trying to convert w2037.4 09:00 to a date time.
I ultimately would like to have the above be 09/10/2020 09:00.
I've tried ParseDate(RXReplace([value],"w"," ","i"),"yyww.d HH:mm") but this is definitely not it.
Any help is appreciated, thanks.
I hope this helps, even if it does not provide a complete answer.
I think the date you are looking for is 10th September (and not 9th October, as I had initially thought - please remember to specify date formats as they vary across countries).
From my understanding, your original column is made of
a w character
last two digits of year 2020
week 37
day of week 4
then the time portion
I cannot find in Spotfire a function that gives you the date from week and day of week. Can you use a TERR expression?
This one worked for me for the specific example you gave, but it is not bullet proof - weeks and days of week are tricky as they depend on your local/regional settings. In my case, I subtracted one day to make it work but you probably don't want it. Also, open source R and TERR give different results with week formats.
So the TERR Expression function I used is:
mydatetime=sapply(input1,function(x) sub('w','',x)) #remove the w
turnToDate = function(x) {
x.vector=strsplit(x,' ')[[1]] #separate date and time parts
x.date=x.vector[1] #store date portion
#is this correct? Remove if not!
x.date=as.character(as.numeric(x.date)+.1) #add a day
x.time=x.vector[2] #store time portion
y.date=as.Date(x.date,format = "%y%W.%w",tz='GMT') #convert week to date
y.datetime=paste(y.date,x.time) #add time as string
return (as.POSIXct(y.datetime,origin="1970-01-01 00:00:00"))
}
#do not use sapply as dates turn to numbers
output=Reduce(c,lapply(mydatetime,turnToDate))
I created it (from the Data>Data Function properties>Expression Functions menu) with the name TERR_convert, as a column function returning a DateTime. Then created a calculated column as :
TERR_convert([value])

Number of minutes in a time range - EXCEL

I have a sheet for tracking my hours at work. We also have a time period between the hours of 07:30 & 18:00 where we can accrue 'flex time'. I want to know from my in and out times, how many hours:minutes I have made in flex.
Please can someone help with the calculation?
The standard way of doing these is to use the overlap formula for two intervals
=max(0,min(end1,end2)-max(start1,start2))
So in your case it would be
=MAX(0,MIN(C2,TIMEVALUE("18:00"))-MAX(B2,TIMEVALUE("7:30")))
If some of your time cells contain strings instead of numbers you would need to check for these. One way of doing it is
=IFERROR(MAX(0,MIN(C2+0,TIMEVALUE("18:00"))-MAX(B2+0,TIMEVALUE("7:30"))),0)
If you ever did a night shift including midnight the formula would need further modification.
Fixed my formula to get correct answers. Bit odd but works now!
=C4+IF(A4-TIME(7,30,0)<0,A4-TIME(7,30,0),0)-IF(B4-TIME(18,0,0)>0,B4-TIME(18,0,0),0)
We take the total time then
if our time starts earlier than flex time starts, we ADD the difference between our start time and flex time, which of course will be a negative number
if our end time ends later than flex time ends, we SUBTRACT the difference between our end time and flex time

Calculate annual leave between two dates in Excel

This task seems easy enough yet I just can't figure a way of doing this without resorting to vba.
All I need is to know the number of hours an employee has used up on annual leave, based on a start and end date, and their hours of work.
To be more clear, this example shows one employees contracted hours from Monday to Sunday i.e. they work only Weds, Thurs, and Friday, for 7.5 hours each day.
Below shows the start and end date that the employee has chosen to take for annual leave. I need to calculate, based on their contracted hours, how much annual leave is used between the two dates. The answer would be 45 hours in this case.
Here's another approach - I've expanded the days between the start and end dates into an array then used the resulting day numbers to offset into the days of work range
=SUMPRODUCT(N(OFFSET(A3,0,WEEKDAY(ROW(INDIRECT(A6&":"&B6)),2)-1)))
If you had a list of holiday dates somewhere (say in I3:N3) you could exclude them as follows
=SUMPRODUCT(N(OFFSET(A3,0,WEEKDAY(ROW(INDIRECT(A6&":"&B6)),2)-1))*ISNA(MATCH(ROW(INDIRECT(A6&":"&B6)),I3:N3,0)))
- it is a bit long-winded but the only way I can think of at the moment.

How to get the difference in minutes between two dates in Microsoft Excel?

I am doing some work in Excel and am running into a bit of a problem. The instruments I am working with save the date and the time of the measurements and I can read this data into Excel with the following format:
A B
1 Date: Time:
2 12/11/12 2:36:25
3 12/12/12 1:46:14
What I am looking to do is find the difference in the two date/time stamps in mins so that I can create a decay curve from the data. So In Excel, I am looking to Make this (if the number of mins in this example is wrong I just calculated it by hand quickly):
A B C
1 Date: Time: Time Elapsed (Minutes)
2 12/11/12 2:36:25 -
3 12/12/12 1:46:14 1436.82
I Have looked around for a bit and found several methods for the difference in time but they always assume that the dates are the same. I exaggerated the time between my measurements some but that roll over of days is what is causing me grief. Any suggestions or hints as to how to go about this would be great. Even If I could find the difference between the date and times in hrs or days in a decimal format, I could just multiple by a constant to get my answer. Please note, I do have experience with programming and Excel but please explain in details. I sometimes get lost in steps.
time and date are both stored as numerical, decimal values (floating point actually). Dates are the whole numbers and time is the decimal part (1/24 = 1 hour, 1/24*1/60 is one minute etc...)
Date-time difference is calculated as:
date2-date1
time2-time1
which will give you the answer in days, now multiply by 24 (hours in day) and then by 60 (minutes in hour) and you are there:
time elapsed = ((date2-date1) + (time2-time1)) * 24 * 60
or
C3 = ((A3-A2)+(B3-B2))*24*60
To add a bit more perspective, Excel stores date and times as serial numbers.
Here is a Reference material to read up.
I would suggest you to use the following:
Combine date to it's time and then do the difference. So it will not cause you any issues of next day or anything.
Please refer to the image with calculations. You may leave your total minutes cell as general or number format.
MS EXCEL Article: Calculate the difference between two times
Example as per this article
Neat way to do this is:
=MOD(end-start,1)*24
where start and end are formatted as "09:00" and "17:00"
Midnight shift
If start and end time are on the same day the MOD function does not affect anything. If the end time crosses midnight, and the end is earlier then start (say you start 23PM and finish 1AM, so result is 2 hours), the MOD function flips the sign of the difference.
Note that this formula calculates the difference between two times (actually two dates) as decimal value. If you want to see the result as time, display the result as time (ctrl+shift+2).
https://exceljet.net/formula/time-difference-in-hours-as-decimal-value
get n day between two dates, by using days360 function =days360(dateA,dateB)
find minute with this formula using timeA as reference =(timeB-$timeA+n*"24:00")*1440
voila you get minutes between two time and dates
I think =TEXT(<cellA> - <cellB>; "[h]:mm:ss") is a more concise answer. This way, you can have your column as a datetime.

Resources