Keep format time in array (VBA Excel) - arrays

I put several data (Names, dates, times and values) into an array. It goes wrong with the date and time.
Where do I go wrong? Here is a piece of my code:
For i = 1 To LastRow + 13
For j = 1 To 10
strArray(i, j) = Cells(i, j).Value2
Next j
Next i
So 0,000983796 should become 0:01:25.

In Excel, a date is the number of days since January 1, 1900 starting
with January 1, 1900 being “1”. Each date after that, Excel adds one
more number to that sequence. So August 26, 2013 is 41512, or 41,512
days since January 1, 1900.
The integer part of the number is used for the days. The decimal part
of the number is the fractional part of the day — or the time. So .5
would be 50% of the way thru the day, or 12:00 noon. That makes
41,512.5 to be equivalent to 12:00 noon on August 26, 2013.
From DATE VALUES IN EXCEL EXPLAINED
You can convert this number value back into something more pretty and readable.
dim pretty as String
pretty = Format(Cells(i, j).Value2, "h:mm:ss")
More examples on vba formatting

Related

Create array of dates/times between set hours

I'm trying to create a horizontal, ascending ARRAY of date/times but only including times that I specify (8:00AM-5:00PM). I've tried using NETWORKDAYS.INTL, but that seemed to be more difficult and inevitably, did not render accurate results the way I was doing it (probably incorrectly).
February 1, 2020 8:00AM
February 1, 2020 9:00AM
[all hours in between]
February 1, 2020 4:00PM
February 1, 2020 5:00PM
February 2, 2020 8:00AM
[...]
February 2, 2020 5:00PM
February 3, 2020 8:00AM
I'm able to do the formula for the first day, but I'm stumbling at adding the following days.
Here is what I have at the moment:
=IF(
AND(J2>=$E1+$B1,J2<$E1+$C1),
J2+(1/24),
J2-$C1+$B1
)
J2 = The first date in the array =EOMONTH(TODAY(),-1)+1+[8:00AM]
E1 = First day of the month =EOMONTH(TODAY(),-1)+1
B1 = Start time 8:00AM
C1 = End time 5:00PM
Here is my sheet. My formula is in K2 (currently dragging the formula across the row, but a single formula would be ideal.)
EDIT:
After playing with it and discovering ROUNDDOWN to extract the date, I came up with this:
=IF(
AND(J2>=ROUNDDOWN(J2,0)+$B1,J2<ROUNDDOWN(J2,0)+$C1),
J2+(1/24),
ROUNDDOWN(J2,0)+1+$B1
)
I think this will work based on some other discussions we had. it is an automatically generated array that will show just the date for the past 2 weeks. then the date and time for the upcoming two weeks, then just the date for 2 weeks after that. You'll see the number 42 in the SEQUENCE portion of the formula. this controls the overall number of days that the formula works for. You'll also see TODAY()-14. This is when the array is set to "start".
=ARRAYFORMULA(TRANSPOSE(TODAY()-14+QUERY(SEQUENCE(42*24,1,0)/24,"where (Col1 % 1=0 and Col1<14) or (Col1 % 1=0 and Col1>=28) or (Col1 % 1<="&N(C1+0.000001)&" and Col1 % 1>="&N(B1)&" and Col1>=14 and Col1<29)",0)))
try:
=ARRAYFORMULA(E1-1+
SPLIT(QUERY(TRANSPOSE(REPT(TRANSPOSE(ROW(INDIRECT("A1:A"&
DAYS(EOMONTH(E1, 3), E1))))&" ",
HOUR(C1)-HOUR(B1)+1)),,9^9), " ")+
SPLIT(REPT(QUERY((ROW(INDIRECT("A1:A"&
HOUR(C1)-HOUR(B1)+1))+HOUR(B1)-1)/24&" ",,9^9),
DAYS(EOMONTH(E1, 3), E1)), " "))
to change span from 3 months to one replace those two 3 for two 1
shorter, faster, lightweight mathematical solution:
=ARRAYFORMULA(SPLIT(QUERY(TRANSPOSE(QUERY(TRANSPOSE(ARRAY_CONSTRAIN(
N(E1)+SEQUENCE(DAYS(EOMONTH(E1, D1-1), E1), 24, HOUR(B1))/24,9^9,
1+HOUR(C1)-HOUR(B1))),,9^9)),,9^9), " "))
While this does solve my overall problem, it's not the ultimate formula I'm seeking which would be a single ARRAYFORMULA.
=IF(
AND(J2>=ROUNDDOWN(J2,0)+$B1,J2<ROUNDDOWN(J2,0)+$C1),
J2+(1/24),
ROUNDDOWN(J2,0)+1+$B1
)
#MattKing solution:
=ARRAYFORMULA(TRANSPOSE(EOMONTH(TODAY(),-1)+1+QUERY(MOD(
SEQUENCE(SUM({-1,1}*EOMONTH(TODAY(),{-1,D1}))*24,1,0)/24,{9^99,1}),
"select Col1 where Col2<="&N(C1+0.000001)&" and Col2>="&N(B1),0)))

Compare two dates and get difference in exact days, months, years, and more SQL Server 2008 R2

I am comparing two dates in SQL Server and need following information in precise manner:
Input:
Start Date = 12/28/2015
End Date = 12/25/2020
Result returned (each piece in different column):
Days = 1825 (includes start/end date in calculation)
Years = 4
Months = 11
Days = 28
How many days in Start Month = 31 days (Because it is December)
Occupancy in Start Month = (because December has 31 days, it would be 4/31) = .12903225806
How many days in End Month = 31 days (Because it is December)
Occupancy in End Month = (because December has 31 days, it would be 25/31) = .8064516129
For 1-3, you can check https://www.w3schools.com/sql/func_sqlserver_datediff.asp. It's fairly simple, you can just use datediff and specify the unit of interest.
For 4, you can simply do day(Start Date) to get the date.
For 5 and 7, you can use:
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#myDate)+1,0)
to get the end of month date of the given date and use day() to get the day part of the datetime object.
For 6 and 8, it's just simple math, you get number of month in that month from 5 and 7, and then, if Start Date, then (day(eom(Start Date)) - day(Start Date) + 1) / day(eom(date) and if End Date, then day(End Date) / day(eom(End Date)).
I didn't give you the full code as I don't have SQL server running besides me. Hope it helps.

Matlab: Number of observations per year for very large array

I have a large array with daily data from 1926 to 2012. I want to find out how many observations are in each year (it varies from year-to-year). I have a column vector which has the dates in the form of:
19290101
19290102
.
.
.
One year here is going to be July through June of the next year.
So 19630701 to 19640630
I would like to use this vector to find the number of days in each year. I need the number of observations to use as inputs into a regression.
I can't tell whether the dates are stored numerically or as a string of characters; I'll assume they're numbers. What I suggest doing is to convert each value to the year and then using hist to count the number of dates in each year. So try something like this:
year = floor(date/10000);
obs_per_year = hist(year,1926:2012);
This will give you a vector holding the number of observations in each year, starting from 1926.
Series of years starting July 1st:
bin = datenum(1926:2012,7,1);
Bin your vector of dates within each year with bin(1) <= x < bin(2), bin(2) <= x < bin(3), ...
count = histc(dates,bin);

How to write expression to display ONLY business days within 5 day frame

I am working on a report in Microsoft SQL Server Report Builder and I am trying to write an expression that will display only the next 5 business days from today (i.e. a table has 5 columns and it starts from today and proceeds for the next five business days). If the day is a Saturday or Sunday, which using my enumeration value would return a 6 or a 7 using the Weekday function, you would skip ahead to the next business day. Currently I have this expression for the first column after the column with today's date
IIf(Weekday(DateAdd("d",1,Today()),2)=6,DateAdd("d",3,Today()),
(IIf(Weekday(DateAdd("d",1,Today()),2)=7,DateAdd("d",2,Today()),
DateAdd("d",1,Today()))))
and it doesn't work. I believe this is because if we have a day like Wednesday, Thursday, or Friday, not enough days are being skipped over for the weekend days.
If we can assume that you are going to start from a business day then there is a simple formula we can use:
=IIF(6 - WeekDay(Today()) - X < 0, DateAdd("d", X + 2, Today()), DateAdd("d", X, Today()))
where X is the number of days that column is from the start date.
Unfortunately, it breaks down if the start date is a Saturday or Sunday but if you only need it for business days then you are good to go.
I think you have to use previous column value instead of using Today()
So inthe first column it will be the current date. (Apply the same formula if it can start from weekend days).
I think switch case is more easy in this condition.
Formula for current day column
=switch (
Weekday(today) = 6, dateadd("d", 2, today),
Weekday(today) = 7, dateadd("d", 1, today),
Weekday(today) < 6, today
)
In the second column instead of today() use "Fields!previous_column_name.Value".
=switch (
Weekday(dateadd("d", 1, Fields!previous_column_name.Value)) = 6, dateadd("d", 3, Fields!previous_column_name.Value),
Weekday(dateadd("d", 1, Fields!previous_column_name.Value)) = 7, dateadd("d", 2, Fields!previous_column_name.Value),
Weekday(dateadd("d", 1, Fields!previous_column_name.Value)) < 6, dateadd("d", 1, Fields!previous_column_name.Value)
)
In third column use the second column as previous_column.
Hope this will help you.

How can I find out all the dates of a given day in this month?

I have to write a program in C which, given the name of a day, returns all of the dates in this month that the day will be on.
For example, if the input is "Sunday" the output should be: 5,12,19,26 (which are the days Sunday will be on this month.)
Does any one have any idea how to do this? I have tried a lot.
You can use the time() function to get the current time.
Then use the localtime() function to get a struct (struct tm) with the information (year, month, day, ...) of the current time.
From the "struct tm" get the tm_mday and the tm_wday. Use these fields to determine the next or previous sunday. e.g. if tm_mday is 12, and tm_wday is 3 (wednesday), then we now that the 9th of this month is a sunday (12-3 = 9). From that number simply add or subtract 7 to get all other sundays.
You need to know it for a given year too? Or is this for only this year? If you need to know it for any given year, you can do a "days per month" enum, having one for the leap years and one for the non-leap years.
You just need to know in which day of week started a year (i.e: "Monday", "Tuesday", etc)
You will, at least, have 5 dates for any given month, so, you can have a fixed length array of ints.
You know that the gregorian calendar repeats itself each 400 years, and that if a year X started with day "Y", then, year X + 1 will start with day ("Y" + 1) % 7 if x is not a leap year, if it is a leap year, it will start with day ("Y" + 2).
that could give you the first date of any year, and knowing how many days have all the months for any given year, you can easily get what date that month starts in ("Monday", etc).
Then, all you have to do, is something like
int offset = 0;
int i;
while (myDate + offset != monthStartingDate) {
offset++;
}
i = offset + monthStartingDate;
(myDate is the number of day of week, and monthStartingDate is the number of day of week for the first day of that month)
when you go out of that loop, you will have the first ocurrence, then, you just add 7 until i is out of month bounds.
you can add each i into the array..
int res[5] = {0,0,0,0,0}
for ( ; i < daysOfMonth(month, year); i += 7) {
int res[i / 7] = i;
}
then you just return res.
Oh, I dind't know that you were able to use date functions :P I think the idea of the excercise was practicing C :P
1) Take a string (weekday name) from the input (use scanf or gets)
2) Convert it to a number (find it's index in a table of weekdays using loop and strcmp), assign 0 to Sunday, 1 for Monday ...
3) Get current time with time function and convert it to tm struct with localtime function
4) From tm struct calculate the first day in current month of a given weekday
first_mday_of_given_wday = (tm_struct.tm_mday + given_wday - tm_struct.tm_wday + 6) % 7 + 1
5) Find out how many days is in current month. To do this:
put 1 into tm_mday and 0 into tm_isdst of your tm struct
duplicate the struct
increase by 1 tm_mon in the duplicate (watch for the last month! in that case increase tm_year by 1 and set tm_mon to 1)
convert booth strutcs to time_t with mktime function and calculate difference (just subtract these time_t values), convert result from seconds to days (divide by 60*60*24)
6) Run a loop though calculated range:
for (i = first_mday_of_given_wday; i <= num_days_in_month; i += 7) printf("%d, ", i)
5th step can be omitted in a certain situations. We know that a month can have from 28 to 31 days. If any of hypothetical days 29,30,31 of current month cannot be a given weekday we can assume that current month has 28 days.
So simply - assume we have 28 days in current month if first_mday_of_given_wday is more then 3, otherwise calculate the number like shown in 5th step.

Resources