Convert 'x hrs y min z sec' to seconds - excel

a) So I have a huge folder of .csv data with a column about time duration where the cells are 'x min y sec' (e.g. 15 min 29 sec) or 'x hrs y min z sec' (e.g. 1 hrs 48 min 28 sec). The cells are formatted by text.
I want to batch change them to the number of seconds, but I have no idea where to start. I can't get the data in another format.
I thought about somehow using 'hrs', 'min' or 'sec' as delimiters, but I don't know how to move from there. I also thought about using ' ' as delimiters, but then the first column is filled with either hours or minutes depending on the time duration.
I also thought about using PostgreSQL's SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours'), but I haven't been able to work out how to use this on a column from a table.
b) Is there a better way to change this time format 'Fri Mar 14 11:29:27 EST 2014' to epoch time? Right now I'm thinking of using macros in Excel to get rid of 'Fri' and 'EST', then put the columns back together, then use the to_timestamp function in PostgreSQL.

In Excel if you have data in only those 2 formats and starting from A2 you can use this formula in B2 copied down to get the number of seconds:
=IFERROR(LEFT(A2,FIND("hrs",A2)-1)*3600,0)+SUM(MID(0&A2,FIND({"min","sec"},0&A2)-3,2)*{60,1})
It finds the relevant text then gets the number in front for each and multiplies by the relevant number to get seconds

You can do:
SELECT EXTRACT(EPOCH FROM column_name::interval)
FROM my_table;
The interval can use the regular time units (like hour), abbreviations thereof (hr) and plurals (hours). I am not sure about a combination of plural and abbreviation (hrs) though. If that does not work, UPDATE the column and replace() the sub-string "hrs" to "hours".
If you want to save the number of seconds in your table, then you convert the above statement into an UPDATE statement:
UPDATE my_table SET seconds_column = extract(epoch FROM column_name::interval);

I would split with space as the delimiter, then examine the second column. If it contains the string "hrs", then your seconds answer is:
3600 * column 1 + 60 * column 3 + column 5
Otherwise it is:
60 * column 1 + column 3

Related

Summing time fields over 24 hours in Power Query

I have a Power Query in excel linked to another file. This file has a time column. I understand that M language will not sum above 24 hours automatically without some work as it uses a datetime reference hence if I import a time of 25 hours it reverts back 2 hours to 1 hour...
In the 3rd column along in my image below using the second row as a reference, this is actually supposed to read 47:47:38. How can I get the instances where the value is above 24 hours to show the true hours?
I have tried using duration.hours(#hours()) this also does not work for some reason.
The same data from the source excel file is below also
Power Query doesn't have custom formats for how it displays data. If you have it read your data as a Duration instead of a DateTime it will display as [d].hh.mm.ss format, but still not with the total hours. Ultimately though this doesn't really matter because even when your data is formatted to display total hours in Excel, it's really being stored internally as days+hours+minutes+seconds. So how it displays in Power Query doesn't matter, as you can just use the hour formatting wherever you output the data to.
Now if you need to use the hours for a calculation between something that isn't another Duration, you can extract the hours by doing
Duration.Days([Your Hours]) * 24 + Duration.Hours([Your Hours])
Or now that I look at it, there is also a TotalHours function that gives you the hours plus mm:ss as a fractional amount of that
Duration.TotalHours([Your Hours])
Power BI doesn't handle this case very gracefully. A solution could be to convert the duration to a number to make it additive (so you can perform calculations and aggregations) and when you need to visualize it, to convert it to the desired format (HH:MM:SS).
Duration and Time are often confused. When such Excel files are read, the type of the column usually is DateTime, and date 1899-12-31 is added to the "time" part. You can change the data type of the column to be Decimal Number, but the "zero point" in Excel unfortunately is one day off (1899-12-30), so you need to subtract 1 from the result to get the actual "number of days" of the duration (i.e. 0.25 means 06:00:00).
So you must perform some conversion of the data. I would make a new column in the model to get the duration in the lowest granularity that I need (seconds in your example). In Power Query Editor add a custom column to calculate the duration in seconds (where Column1 is the name of the original duration column):
Duration in seconds = Duration.TotalSeconds([Column1] - #datetime(1899, 12, 31, 0, 0, 0))
Make sure the data type of this column is Whole Number (change it if necessary). Here 9144 seconds are calculated as 2 * 3600 + 32 * 60 + 24, or 02:32:24. Now you can calculate a sum on this column to get total duration in seconds for example. But when you visualize this column, don't do it directly, but make a measure to convert the data to the desired format. It could me made like this:
Measure Duration =
VAR duration_in_seconds = SUM(Sheet1[Duration in seconds])
VAR hours = ROUNDDOWN ( duration_in_seconds / 3600; 0 )
VAR minutes = ROUNDDOWN ( MOD ( duration_in_seconds; 3600 ) / 60; 0 )
VAR seconds = INT ( MOD ( duration_in_seconds; 60 ) )
RETURN hours & ":" & FORMAT(minutes; "00") & ":" & FORMAT(seconds; "00")
duration_in_seconds variable hold the total duration in seconds of the data in the context. From it we are calculating hours, minutes and seconds and constructing a string to represent the duration in the desired format. FORMAT is used to make sure there is a leading zero in case minutes or seconds are less than 10.
Here is how all three columns looks like when visualized:
Hope this helps!

How to check if a time noted is within designated window or range in Excel

I need to check if a time of collection is within allowed time window or not.
For e.g.
A B C
1 10.36 10.30 1 min out of +/- 5 minutes window
2 10.24 10.30 1 min out of +/- 5 minutes window
A1 here time of collection of data, and B1 is the scheduled time. The acceptable window or range for this is +/- 5 minutes out of window. In this case the time of collection is 1 min out of +/- 5 minutes window. Similar example is shown in row 2. How can i get C1 to show the message as above which can account for + 5 minutes and - 5 minutes scenarios?.
Thanks in advance.
=IF(ABS(A1-B1)>(5/1440),"Problem!","OK")
5/1440 is 5 minutes (1440 minutes in a full day)
Use this formula¹ in C1 and fill down as necessary,
=ROUND(MAX((ABS(A1-B1)-0.05)*100, 0), 0)
Use the following custom number format on column C,
0 \mi\n out of ± 5 \mi\nut\e wi\n\dow
The advantages of a custom number format is that the numbers remain numbers and are available for future calculations (e.g. SUM, AVERAGE, etc) while displaying the text you wish to show. Note the right-alignment in the cells indicating true numbers.
¹ This formula depends on the time values being mixed numbers and not true time. If the time values are true time with a non-EN-US number format then additional maths may have to be applied to the formula.

How to count hours in excel

I have xls file in following format
Name 1 2 3 4
John 09:00-21:00 09:00-21:00
Amy 21:00-09:00 09:00-21:00
Where 1,2,3,4 and so on represent days of current month,
09:00-21:00 - working hours.
I want to calculate salary based on the following conditions:
09:00-21:00 - 10$/hour
21:00-00:00 - 15$/hour
00:00-03:00 - 20$/hour
etc.
and so on (every hour can have it's own cost, for example 03:00-04:00 - 20$/hour, 04:00-05:00 - 19$/hour, etc.)
How can i accomplish this using only Excel (functions or VBA)?
P.S. Easy way: export to csv and process in python/php/etc.
Here is a non-VBA solution. It's a pretty nasty formula, but it works. I am sure it could be made even easier to use and understand with some more ingenuity:
Assuming the spreadsheet is set up like this:
Enter this formula in cell G1 and drag down for your data set:
=IF(ISBLANK(B2),"",IF(LEFT(B2,2)<MID(B2,FIND("-",B2)+1,2),SUMIFS($P$2:$P$24,$Q$2:$Q$24,">="&LEFT(B2,2),$Q$2:$Q$24,"<="&MID(B2,FIND("-",B2)+1,2)),SUMIF($Q$2:$Q$24,"<="&MID(B2,FIND("-",B2)+1,2),$P$2:$P$24)+SUMIF($Q$2:$Q$24,">="&LEFT(B2,2),$P$2:$P$24)))
To explain the formula in detail:
IF(ISBLANK(B2),"" will return a empty string if there is no time for a given person / day combination.
LEFT(B2,2) extracts the start-time into an hour.
Mid(B2,Find("-",B2)+1,2) extracts the end-time into an hour.
IF(LEFT(B2,2)<MID(B2,FIND("-",B2)+1,2) will check if the start-time is less than the end-time (meaning no over-night work). If the start-time is less than the end-time, it will use this formula to calculate the total cost per hour: SUMIFS($P$2:$P$24,$Q$2:$Q$24,">="&LEFT(B3,2),$Q$2:$Q$24,"<="&MID(B3,FIND("-",B3)+1,2))
If the start-time is higher than the end-time (meaning overnight work), it will use this formula to calculate: SUMIF($Q$2:$Q$24,"<="&MID(B3,FIND("-",B3)+1,2),$P$2:$P$24)+SUMIF($Q$2:$Q$24,">="&LEFT(B3,2),$P$2:$P$24)
The use of the Find("-",[cell]) splits the start-and- end times into values excel can use to do math against the Time / Cost table.
The formula in column Q of the Time / Cost table is =VALUE(MID(O2,FIND("-",O2)+1,2)) and turns the ending hour to consider the cost into a value Excel can use to add, instead of having the text from your original source format.
Do this in VBA! It is native to excel and is easy to learn. Functionally, I would loop through the table, write a function to calculate the dollars earned based on the info given. If you want your results to be live updating (like a formula in excel) you can write a user defined function. A helpful function might be an HoursIntersect function, as below:
Public Function HoursIntersect(Period1Start As Date, Period1End As Date, _
Period2Start As Date, Period2End As Date) _
As Double
Dim result As Double
' Check if the ends are greater than the starts. If they are, assume we are rolling over to
' a new day
If Period1End < Period1Start Then Period1End = Period1End + 1
If Period2End < Period2Start Then Period2End = Period2End + 1
With WorksheetFunction
result = .Min(Period1End, Period2End) - .Max(Period1Start, Period2Start)
HoursIntersect = .Max(result, 0) * 24
End With
End Function
Then you can determine the start and end time by splitting the value on the "-" character. Then multiply each payment schedule by the hours worked within that time:
DollarsEarned = DollarsEarned + 20 * HoursIntersect(StartTime, EndTime, #00:00:00#, #03:00:00#)
DollarsEarned = DollarsEarned + 10 * HoursIntersect(StartTime, EndTime, #09:00:00#, #21:00:00#)
DollarsEarned = DollarsEarned + 15 * HoursIntersect(StartTime, EndTime, #21:00:00#, #00:00:00#)
I have a method that uses nothing but formulas. First create a lookup table which contains every hour and rate in say columns K & L, something like this:
K L
08:00 15
09:00 10
10:00 10
11:00 10
12:00 10
13:00 10
14:00 10
15:00 10
16:00 10
17:00 10
18:00 10
19:00 10
20:00 10
21:00 15
22:00 15
23:00 15
Make sure you enter the hours as text by entering a single quote before the digits.
Then if your hours were in cell B2 you could then use this formula to calculate the total:
=SUM(INDIRECT("L"&MATCH(LEFT(B2,5),K2:K40,0)&":L"&MATCH(RIGHT(B2,5),K2:K40,0)))
All the formula is doing is getting the left and right text of your work time, using MATCH to find their positions in the lookup table which is used to create a range address which is then passed to SUM via the INDIRECT function.
If you need to worry about minutes all you need to do is create a bigger lookup table which holds every minute of the day. You may need to add some extra logic if your work days span midnight.

Computing Average In MM:SS in excel

Input: Minutes:Seconds
Output: Average in Minutes:Seconds
I currently have a sheet where we put in handle times for calls. We want to compute the average handling time in minutes:seconds. Now, currently we have minutes in Column A and seconds in Column B. In Column C, I convert A&B to total seconds. In Column D, I use =AVERAGE(C1:C6) to compute for average.
Question: Do we have an easier way to doit? Specifically, is there any formula that will allow me to simply input Minutes:Seconds in a single column and have the average in Minutes:Seconds to be calculated?
Option 1:
(If you can change your input format):
You need to set the data format as hh:mm:ss
Inputting the data in this format will allow excel to automatically detect the format and as such, allow for you to use the 'average' formula.
For example, if you have 3 entries for: 2 minutes, 1 min 30 secs and 1 minute, the data in col A should look like:
00:02:00
00:01:30
00:01:00
You can then run, for example, the formula:
=AVERAGE(A1:A3)
Note: By default, putting the data in the format "xx:yy", excel will assume that xx is the hours and yy is the minutes, so you should pass the initial 00: if you don't have your time in hours
Option 2:
(If you cannot change your input format):
If you need to stick to the format where col A contains the minutes and col b contains the seconds, you can use the following formula to pass "hh:mm:ss" data in col c:
=(A1/(24*60))+(B1/(24*60*60))
(default date value is set to '1 day' for a cell, so we divide by 24 hrs and 60 mins to convert it to 'minutes' from col A and 24*60*60 to get seconds from col B)
You can then use a folmula similar to the one below to calculate the average time in col C:
=AVERAGE(C1:C3)
Note: You would need to set column C to the 'Custom format':
hh:mm:ss

Excel VBA to count records that have a certain number of elapsed seconds

I am trying to report "Number of Elapsed Seconds" in these breaks: Less than 15 minutes, 15 to 19 min, 20 to 24 min, 25 to 29 min, 30 to 45 min, 45 to 60 min, and 60 min or more.
I have a field that shows elapsed seconds and I am able to get the breaks I want -- In Total -- by using the following formula:
=SUMPRODUCT((ABS(TestTable!$AF$2:$AF$50)>=0)*(ABS(TestTable!$AF$2:$AF$)<=899))
(where 'TestTable' is the sheet where the data is located and Col AF is where elapsed seconds is stored). The problem?
I need to cut each break down by another field. Also in 'TestTable' is a field with either PRODx or PRODz in it (it's Col H).
So I need to say "If Col H = PRODx, then count how many records are less than 15 min and put it in a certain cell ---THEN--- if Col H = PRODz then count how many records are less than 15 min and put that result in a different cell".
Anybody know a way to write this?
if you have excel 2007 or later, COUNTIFS should work out for you.
=COUNIFS(H:H,AF:AF,"<900",H:H,"PRODx") for less than 15 mins, and PRODx
=COUNIFS(H:H,AF:AF,"<900",H:H,"PRODz") for less than 15 mins, and PRODz
then for the ranges you expand the selection
=COUNIFS(H:H,AF:AF,">=900",AF:AF,"<1200",H:H,"PRODx") for 15-19 mins, and PRODx
=COUNIFS(H:H,AF:AF,">=900",AF:AF,"<1200",H:H,"PRODz") for 15-19 mins, and PRODz
keep repeating this for all the ranges of time/PRODs that you need
In cell A1, type:
=COUNT(IF(H:H="PRODx",IF(AF:AF="Less Than 15 Seconds",M1:M5)))
M is just another random column
In cell A2, type the same, but change PRODx to PRODz.
Make sure to enter all formulas as an array formula, by hitting CTRL + SHIFT + ENTER after typing, instead of just enter.
See this link for more: Count If WIth Multiple Criteria
EDIT
If you must have a VBA solution, let me know. Otherwise, you don't need VBA. Also, if you are running Excel 2007 or above, you can use the CountIfs function, which will be cleaner and less resource intensive than the Array formula above.

Resources