Formula to calculate projected end time and actual end time - google-sheets

I have two columns:
Projected End Time
Actual End Time
Projected End Time-Actual End Time gives the difference. E.g.
=SUM(K3-J3) -where K3 is Actual End Time and J3 is Projected End Time
So, for example,
3:50 PM | 3:55 PM - the difference shows as 0:05 - which is correct.
But on the other hand,
3:50 PM | 3:45 PM - the difference shows as 23:55. What I want is the savings, i.e., +0:05 mins. How can I fix this?

I made some tests, you can test if this formula works for you. If you have any issues let me know.
The test table I made is:
And the formula is:
=if(SUM(K3-J3)<0,"+"&TEXT(ABS(SUM(K3-J3)),"h:mm"),TEXT(ABS(SUM(K3-J3)),"h:mm"))
So the result look like this:
I basically use an if statement to separate the negative results and the positive ones. If the value is negative like in the case of:
= (3:45: PM - 3:50: PM) it will take the absolute value of it, and concatenate the “+” symbol with the result of = (3:45: PM - 3:50: PM). However, to get the right format of the result, I use the text formula.
If the number is higher than “0” or “0” then it will use the normal formula, and add the correct format using Text.

Related

How to SUM duration in Google Sheets?

Time started time end Duration
6:02:53 PM 6:11:07 PM 0:08:13
6:11:22 PM 6:20:33 PM 0:09:11
6:20:48 PM 6:32:21 PM 0:11:34
6:32:44 PM 6:39:04 PM 0:06:20
6:39:28 PM 7:00:41 PM 0:21:13
7:01:00 PM 7:09:16 PM 0:08:16
7:09:40 PM 7:16:03 PM 0:06:23
7:16:03 PM 7:24:21 PM 0:08:17
7:24:45 PM 7:30:57 PM 0:06:12
7:31:27 PM 7:37:21 PM 0:05:54
7:37:21 PM 7:44:06 PM 0:06:45
I want sum of all duration entries in x hours x minutes x seconds like i have more then 1000 rows of duration when i try to use =SUM(C2:C100) I am not getting sum of total duration after sum of 24:00:00 24 hours it starts from 00:00:00
for example sum of total duration gets 24:00:00 between range of c1:c8 it will start from 00:00:00 from c9: next range kindly assist me how to overcome this issue
try:
=ARRAYFORMULA(TEXT(SUM(IFERROR(TIMEVALUE(C:C))), "[h]:mm:ss"))
spreadsheet demo
Wherever you put the =SUM(), Select that cell and do Format>Number>More Formats>Custom Number formatting, and put the same formatting that Player0 put in his answer:
What worked for me to resolve a similar problem was a suggestion by user ttarchala in Google Sheets Query multi condition sum of time duration.
I used N() function as he said, and my final formula for the duration is:
=IF(To<>"", N(To-From+(To<From))*24, "")
with To and From being Named ranges for End Time and Start Time respectively.
N() function converts the time delta into a number. Multiplied by 24, this gives the hours in decimal format, such as 2 hours 30 minutes = 2.5 hours.
From there on, there is no problem with using the built-in Sum function to calculate the total duration as a decimal. Such as, the total duration of 27 hrs 10 minutes is shown as 27.16. This sufficed for my purposes.
Time delta is calculated using a formula from https://webapps.stackexchange.com/questions/104829/calculate-time-difference-between-times-past-midnight to take into account past-midnight differences.
And the first condition, To<>"", makes sure the formula is not showing in empty cells. As soon as the End Time is filled into "To" column, the decimal duration is calculated. Then it can be used in the regular Sum function.
This seemed shorter and easier than the formulas suggested above so I am sharing it in the hopes it may help someone else. Using thus formula, I just added up the Sum of time I spent looking for this solution: 3.34 hours :)
It's a formatting problem. You formatted your reply as HH:MM:SS, therefore the number displayed is not showing the date, which would have been incremented by one. If you multiply your sum by 24, and then format the result as a pure number, you will get a number that goes above 24, and will show you the number of hours, and its decimals. If you use those hours in further calculations, the result will be correct.
In cell C1, use the formula
=IF((B1-A1)>=0, B1-A1, 1+B1-A1)
Explanation: the problem is durations that exceed the 24 hour limit, as you say.
Google Sheets has become a bit deceptive here, as it will show the correct duration for the individual time interval, but if you SUM over it, it will actually deduct the value!
A B C
23:39 1:10 1:31
When you SUM then Google Sheets will see the value in cell C1 as if it was the beginning of the same day as the time in A1. So when you in C1 do =B1-A1 then it will register as a negative duration! But it won't show up as that!
In C1 use this formula, =IF((B1-A1)>=0, B1-A1, 1+B1-A1) for individual cells in column C, when you see that cells in column B has exceeded the 24-hour limit once. The duration in C1 should still show 1:31, but now the result when doing SUM over a range of cells in column C, like =SUM(C1:C2), will now show the correct and strictly additive sum. You can safely copy this formula to all cells in column C.
PS: cells in all of the columns can have Automatic or no formatting (which I think defaults to Automatic), if your time inputs look like the above. So you don't need to format all of those cells to Time or Duration. BUT remember to format the SUM cell to Format -> Number -> Duration.
PPS: if you are manually inputting the times (for for instance time tracking), then the easiest way to keep the much simpler =B1-A1 formula is to split the time up into two rows, like this:
A B C
23:39 0:00 0:21
0:00 1:10 1:10
Then the SUM of cells in column C still becomes 1:31.

How to get date out of a cell containing the string "2017|03"?

Here is my data:
I am trying to build a SUMIFS formula to sum the sessions, if the month = "last month" (i.e., parsed out of these strings), and the Channel Grouping = "Display".
Here's what I have so far:
=SUMIFS(H3:H,F3:F,________,G3:G,"Direct")
Since this is a string, not a date, I am not sure how to get it to match "last month".
Why not build up a string like this (or just hard-code it?)
=sumifs(H3:H,F3:F,year(today())&"|"&text(month(today())-1,"00"),G3:G,"Direct")
This builds up a string equal to "2017|03" by taking the year from today's date (2017) and one less than the month number from today's date which at time of writing is April so 4-1=3. The text function formats it with a leading zero. So the whole thing is"2017" & "|" & "03" which gives "2017|03" - this is compared against column F.
Note: January would be a special case (existing formula would give "2018|00" for previous month to January 2018 so would need a bit of extra code to cover this case and make it fully automatic).
By 'hard-code it' I mean just put 2017|03 in as a literal string like this
=sumifs(H3:H,F3:F,"2017|03",G3:G,"Direct")
then just change it manually for different months.
Here is a more general formula
=sumifs(H3:H,F3:F,year(eomonth(today(),-1))&"|"&text(month(eomonth(today(),-1)),"00"),G3:G,"Direct")
Just change the -1 to -2 etc. for different numbers of months.
EDIT
In light of #Max Makhrov's answer, this can be shortened significantly to
=sumifs(H3:H,F3:F,text(eomonth(today(),-1),"YYYY|MM"),G3:G,"Direct")
I would like to add two more options:
1
This formula is slightly shorter and more powerrful, because it gives the full control over date format:
=TEXT(TODAY(),"YYYY|MM")
formula syntax is here:
https://support.google.com/docs/answer/3094139?hl=en
2
In your case converting date to string is more efficient because it calculates one time in the formula, so there's fewer calculations. But sometimes you need to convert text into date. In this case I prefer using regular expresions:
=JOIN("/",{REGEXEXTRACT("2017|03","(\d{4})\|(\d{2})"),1})*1
How it works
REGEXEXTRACT("2017|03","(\d{4})\|(\d{2})") gives 2 separate cells output:
2017 03
{..., 1} adds 1 to ... and adds it to the right:
2017 03 1
JOIN("/", ...) joins the ... input:
2017/03/1
This looks like date, but to make it real date, multimpy it by 1:
"2017/03/1"*1 converts string that looks like date into a number 42795 which is serial number for date 2017 march 01

Ruby Regular Expression to validate day and month of a date

On rubular I tested and confirmed that this does a good job confirming the desired format of a date entry:
\A\d\d\/\d\d\/\d\d\d\d\z
Tests:
01/02/2000 #pass
11/21/2014 #pass
11-21-2014 #fail
A3-21-2014 #fail
I want to make it a little bit better, and it will be good enough for me. What I want is to confirm that the "month field" (the first two digits) is anywhere from 01 - 12, where each single digit is led by a zero. (Ex: 01,02,03 etc as opposed to: 1,2,3).
Next: I want to do the same thing for the next two digits to confirm that the next two digits (the day field) is between 01 - 31. Same thing: Each single digit needs to lead with a zero.
Tests:
01/02/2017 #pass
12/31/2017 #pass
1/02/2017 #fail
01/2/2017 #fail
50/01/2017 #fail
01/50/2017 #fail
I realize that this regex will be inaccurate for those months that have fewer than 31 days, but it is good enough for what I am doing.
Well this should get you most of the way there:
/((02\/[0-2]\d)|((01|[0][3-9]|[1][0-2])\/(31|30|[0-2]\d)))\/[12]\d{3}/
Granted it does not handle the following:
Leap Years e.g. 02/29 is acceptable regardless of the year
All Years from 1000-2999 are acceptable
Months with only 30 days e.g. 09/31 is acceptable
Small Breakdown in case links break:
Here is the runout on Rubular
Here is an explanation from Regex101
(02\/[0-2]\d) - Starts with 02/ then allow 0-2 followed by 0-9
OR ((01|[0][3-9]|[1][0-2]\/(31|30|[0-2]\d)) - Starts with (01 or 0 followed by 3-9 or 1 followed by 0-2) followed a / followed by 31 or 30 or 0-2 followed by 0-9
In both cases must be followed by 1 or 2 followed by 3 digits 0-9
Really wish ruby supported look behind conditionals like true pcre Example for edification
As a Note: as mentioned in the comments rescuing a parsing failure is probably easier than using a regex but I figured since you asked.
What I did was used the american_date gem. On your date inputs: the user should enter the date in the format of: "mm/dd/yyyy".
In order to force the user to enter the date in this format: I used jquery-inputmask-rails. I defined my mask like so:
$('.mask_american_date').inputmask({mask: "99/99/9999"});
Now there will be a nice mask on the date input that looks like this:
__/__/____
Now: all you need is a presence validator for the date field in your model:
validates_presence_of :date_of_birth, message: "Date is either invalid or is not present".
And this covers everything. How american date works is it takes the user input and attempts to convert it into a date. If it cannot convert the user input into a date for any reason: it will return nil which triggers the above validation.
This includes a bad month entry or a bad day entry. American Date is smart enough to know, for example, that September only has 30 days in it. So: if the user enters "31" for the day section, ex: 09/31/2017, american date will convert the date to nil.

Google spreadsheet, comparing durations

I calculated a duration between two times, e.g. between 9:00 am and 11:00 am. So far so good. Now I need to decide if this duration is less 6 hours.
I do remember that this was pain in the s in excel but nevertheless I tried it the simple way:
=IF(E2 < 06:00:00; "y"; "n")
of course that didn't work. Next:
=IF(DURATION(E2) < DURATION(06:00:00); "y"; "n")
still, it didn't work.
So, okay, how can I compare two duration?
Divide hours by 24:
=IF(E2 < 6/24, "y", "n")
Value is E2 is a formatted time, actually 1 hour is 1/24, 1 day is 1.
Some info about date and time formats here:
http://www.excel-easy.com/examples/date-time-formats.html
You can also use the HOUR function if you want to
=if(HOUR(E2)<6,ʺyesʺ,ʺnoʺ)
or
=if(E2<time(6,0,0),ʺyesʺ,ʺnoʺ)
(if you write 06:00:00 in a formula it takes it as a string not a time)
but as I'm sure someone is about to point out, the first formula above gives the wrong answer for durations of more than a day (because it takes the hour part of a datetime).
What I find interesting is that you can assume for a worksheet formula that dates and times are represented as whole numbers (days) and fractions (parts of a day) just like in Excel. If you ever have to deal with them in Google App Scripts, you suddenly find that it's object-oriented and you have no choice but to use methods like hour() to manipulate them.
I needed to use the equivalent of:
=if(TIMEVALUE(E2)<6/24, "yes", "no")

Moving averages varlist

I am trying to calculate moving averages spanning 30 days (prior moving averages) using SPSS 20 for about 1200 stock tickers. I would like to use a loop like:
Calculate 30 days moving average for a ticker say AAAA or 0001 and save it like MA30AAAA or MA300001.
Take another ticker say AAAB or 0002 and do as above.
Continued until all tickers are captured and MA calculated, saved to new columns.
Do you think I can develop a SPSS Syntax for that.
If I try the following, I get error warnings. Please can you help me get a reasonably well structured syntax to do my job.
There was a very similar question today on LinkedIn (see here or below for the answer).
-Assuming every date is present exactly once in your data, the syntax below will calculate moving annual totals and averages over each date + the preceding 29 dates.
-If fewer than 29 days preceded some date, these new variables will not be calculated for this date. (IMHO, this would be misleading information.)
-The 2 new variables will appear in one column each but with a few extra lines you can put each value into its own column if desired.
Kind regards,
Ruben
*Generate test data.
set seed 1.
input program.
loop #=1 to 60.
if #=1 date=date.dmy(21,11,2012).
if #>1 date=datesum(lag(date),1,"days").
end case.
end loop.
end file.
end inp pro.
if $casenum=1 price=100.
if $casenum ne 1 price=lag(price)+tru(rv.nor(0,5)).
for date(edate10).
exe.
*Compute moving total + average.
comp moving_total_30=price.
do rep dif=1 to 29.
comp moving_total_30=moving_total_30+lag(price,dif).
end rep.
comp moving_average_30=moving_total_30/30.
exe.

Resources