Excel VBA prevent VBA from converting Time values to decimals - datetime

I am trying to extract data from my workbook because I made the workbook wrong but I want to keep the data. So I have to go through each worksheet and extract the specific bits of data I need. (Repetitive task = vba code to the rescue)
I'm done, but I have one nasty little problem.
I am using ws.Range("C13") to extract each cell that I need. It's a cell that has time values like 10:00 or 22:13. When I debug.print that value however I get a decimal. Why? How do I prevent it from converting my "10:30" to "0.4375"
From what I can tell, the decimal isn't even related to the time value.
WRONG it is simply the time value as a representation of a 24 hour period. So it is related. But still.

ws.Range("C13") is the equivalent of ws.Range("C13").Value which returns the underlying data from that cell.
If instead you use ws.Range("C13").Text, you will get the displayed text from the cell. If you have set a specific date/time format for that cell then calling ws.Range("C13").Text should return text in that specific format

The time values are correct; it's the way Excel stores date and time values internally.
Dates are stored as floating point values, where the whole portion represents the number of days since 12/30/1899 00:00.00 (date 0.0) and the decimal part represents the fractional part of a single day (eg., 408875.5 represents 11/28/2011 12:00:00 PM).
Here are some conversion factors you might find useful:
Decimal value Time Value Calculation
============= ========== ===========
0.00094444444 12:01:00 AM 1.0 / 24 / 60 (1 day/24 hours/60 minutes per hour)
0.01041666666 12:15:00 AM 1.0 / 24 / 60 * 15
0.02083333333 12:30:00 AM 1.0 / 24 / 60 * 30
0.04166666666 01:00:00 AM 1.0 / 24

hours = MOD(INT(0.tttttttt*24), 24)
minutes = MOD(INT(0.tttttttt*24*60), 60)
seconds = MOD(INT(0.tttttttt*24*60*60), 60)
milliseconds = MOD(INT(0.tttttttt*24*60*60*1000), 1000)

Related

How to add Two Columns (Date/Time) Together in Tableau

I have a dataset which was imported from Excel to Tableau. In Excel the data is listed as "8:15:00 AM". When it's imported into Tableau it's now Date & Time as "12/30/1899 10:45:00 AM".
What I'm trying to perform is an addition problem between two date & time columns. An example being:
Sleep: 12/30/1899 10:45:00
Eating: 12/30/1899 00:45:00
Sleep + Eating which should yield 10:40 + 00:45 = 11:30
After much googling and video watching, I have not found a solution.
Creating a calculated as such should solve the problem:
DATEADD(
'hour', DATEPART('hour', [Eating]), DATEADD(
'minute', DATEPART('minute', [Eating]), DATEADD(
'second', DATEPART('second', [Eating]), [Sleep])))
From there, the time display of the field can be adjusted as necessary:
Right-click field name > Default Properties > Date Format
You can achieve the desired result by creating three calculated fields. Lets call one of the calculated field [hours] and another one [minutes]. A third field will use the values from [hours] and [minutes] in order to properly display the results. Let's call this third field [Sleep + Eating].
To create [hours]:
//[hours] calculated field
DATEPART('hour', [Sleep])+ DATEPART('hour', [Eating])
To create [minutes]:
//[hours] calculated field
DATEPART('minute', [Sleep])+DATEPART('minute', [Eating])
At this point [hours] and [minutes] are just the sums of the integer values from [Sleep] and [Eating]. To display these sums in the format you have requested, you'll need to have a third calculated field that concatenates hours and the minutes, and is also able to handle a situations where the minutes add up to more than 60, or when the minutes add up to less then 10.[Sleep + Eating] calculated field will achieve this.
Here is the [Sleep + Eating] calculated field:
//[Sleep + Eating] calculated field
IF [minutes]< 10 THEN STR([hours])+":0"+STR([minutes])
ELSEIF [minutes]< 60 THEN STR([hours])+":"+STR([minutes])
ELSEIF [minutes]>= 70 THEN STR([hours]+1)+":"+STR([minutes]-60)
ELSE STR([hours]+1)+":0"+STR([minutes]-60)
END
Other solutions that try to treat your data like a date field (See #Daniel Sims answer) could be problematic if the hours sum to greater than 23, the result will add a day. For example, lets say you had these values in Excel:
If you use my solution, the result will be 25:02. If you use #Daniel Sims answer, the result would be 12/31/1899 1:02 :00 AM, which I don't think is what you want.

Fetch Data At every 2 Minutes SQL Lite

Please can anyone help me in fetching data from my SQL Lite Table at every 2 minutes between my start time and stop time
I have two columns Data , TimeStamp and I am filtering between two timestamp and it is working fine but what I am trying to do is to result my data at every 2 minutes interval For example my start time is 2016-12-15 10:00:00 and stop time is 2016-12-15 10:10:00 the result should be 2016-12-15 10:00:00,2016-12-15 10:02:00,2016-12-15 10:04:00 ....
Add, to your where clause, an expression that looks for 2 minute boundaries:
strftime("%s", TimeStamp) % 120 = 0
This assumes you have data on exact, 2-minute boundaries. It will ignore data between those points.
strftime("%s", TimeStamp) converts your time stamp string into a single number representing the number of seconds since Jan 1st, 1970. The % 120 does modulo arithmetic resulting in 0 every 120 seconds. If you want minute boundaries, use 60. If you want hourly, use 3600.
What's more interesting -- and I've used this -- is to take all the data between boundaries and average them together:
SELECT CAST(strftime("%s", TimeStamp) / 120 AS INTEGER) * 120 as stamp, AVG(Data)
FROM table
WHERE TimeStamp >= '2016-12-15 10:00:00' AND
TimeStamp < '2016-12-15 10:10:00'
GROUP BY stamp;
This averages all data with timestamps in the same 2-minute "bin". The second date comparison is < rather than <= because then the last bin would only average one sample whereas the other bins would be averages of multiple values. You could also add MAX(Data) and MIN(Data) columns, if you want to know how much the data changed within each bin.

Days between dates calculation

I imported date variables as strings from SQL (date1) into Stata and then created a new date variable (date2) like this:
gen double date2 = clock(date1, "YMDhms")
format date2 %tc
However, now I want to calculate the number of days between two dates (date3-date2), formatted as above, but I can't seem to do it.
I don't care about the hms, so perhaps I should strip that out first? And then deconstruct the date into YYYY MM DD as separate variables? Nothing I seems to do is working right now.
It sounds like by dates you actually mean timestamp (aka datetime) variables. In my experience, there's usually no need to cast dates/timestamps as strings since ODBC and Stata will handle the conversion to SIF td/tc formats nicely.
But perhaps you exported to a text file and then read in the data instead. Here are a couple solutions.
tc timestamps are in milliseconds since 01jan1960 00:00:00.000, assuming 1000*60*60*24=86,400 seconds/day (that is, ignoring leap seconds). This means that you need to divide your difference by that number to get elapsed days.
For example, 2016 was a leap year:
. display (tc(01jan2017 00:00:00) - tc(01jan2016 00:00:00))/(1000*60*60*24)
366
You can also use the dofc() function to make dates out of timestamps and omit the division:
. display (dofc(tc(01jan2018 00:00:00)) - dofc(tc(01jan2016 00:00:00)))
731
2017 is not a leap year, so 366 + 365 = 731 days.
You can use generate with all these functions, though display is often easier for debugging initial attempts.

Get total time and create an average based on timestamps

Background: I want to use coldfusion to find the total time a process takes by taking two timestamps and then adding all of the total times to create an average.
Question: What is the best way to take two timestamps and find out the difference in time by minutes.
Example:
Time Stamp #1: 2015-05-08 15:44:00.000
Time Stamp #2: 2015-05-11 08:52:00.000
So the time between the above timestamps would be:
2 Days 6 hours 52 mins = 3,292 minutes
I want to run this conversion on a handful of timestamp's and take the total minutes and divide to get an average.
To add more information to my question. 1. Yes the values are coming from a DB MSSQL. 2. I am actually going to be using the individual time differences and showing and overall average. So in my for loop each line will have a value like 3,292 (converted to mins or hours or days) and at the end of the for loop I want to show an average of all the lines shown on the page. Let me know if I need to add any other information.
Assuming your query is sorted properly, something like this should work.
totalMinutes = 0;
for (i = 2; i <= yourQuery.recordcount; i++)
totalMinutes +=
DateDiff('n'
, yourQuery.timestampField[i-1]
,yourQuery.timestampField[i]);
avgMinutes = totalMinutes / (yourQuery.recordcount -1);
Use the dateDiff() function
diffInMinutes = dateDiff('n', date1, date2);

Date string conversion from R to CSV in Libre Calc

I'm trying to get acquainted with weatherData in R.
Having downloaded a set of temperature data I've then exported it to CSV.
Opening the CSV in Libre Calc shows the date and time for each temperature reading as a string of ten digits. In spite of some Googling I have not found a way of successfully converting the string into the format in which it appears in R.
For example: 1357084200 I believe should translate to 2013-01-01 23:50:00
Any help in getting the correct date in the same date format to appear in Calc via the CSV greatly appreciated.
Here is the direct way:
as.POSIXct(1357084200, origin="1970-01-01", tz="GMT")
#[1] "2013-01-01 23:50:00 GMT"
If it's really a character:
as.POSIXct(as.numeric("1357084200"), origin="1970-01-01", tz="GMT")
I'm not aware of a direct way of doing this, but I believe I've figured out a workaround.
For starters your example is correct. The long number (timestamp) is the number of seconds passed since 1970-01-01 00:00:00. Knowing this you can actually calculate the exact date and time from the timestamp. It's a bit complicated due to needing to take into account the leap years.
What comes in handy is the ability to supply an arbitrary number of days/months/years to LibreOffice function DATE. So in essence you can find out the number of days represented in timestamp by dividing it by 60*60*24 (number of seconds in a minute, number of minutes in an hour, number of hours in a day). And then supply that number to the date function.
timestamp = 1357084200
days = timestamp / FLOOR(timestamp / (60*60*24); 1) // comes out at 15706
actualdate = DATE(1970; 1; 1 + days) // comes out at 2013-01-01
seconds = timestamp - days * 60 * 60 * 24 // comes out at 85800
actualtime = TIME(0; 0; seconds) // comes out at 23:50:00
Then you can concatenate these or whatever else you want to do.

Resources