time difference's seems like working odd? - datetime

I am going to find difference between two times but I am not getting what I want!!!
I have 2 timeEdit components in a form
here is my code:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TTime time1=StrToTime(t1->Text);
TTime time2=StrToTime(t2->Text);
//t1->Text=time2-StrToTime("3:00");
ShowMessage((time2-time1).TimeString());
}
If I set t1 = 02:00
and set t2 = 01:00
it shows 1:00
but I expect 23:00
that is 01:00 - 02:00 should be 23:00
where I am wrong ?

You are not taking into account how TTime is encoded. TDateTime is a Double, where the integral portion contains the number of days since Dec 30 1899, and the fractional portion contains a percentage of a 24-hour day (this information is stated in the C++Builder documentation). TTime is just the fractional portion of a TDateTime with its integral portion ignored. Because of this encoding, performing such seemingly simple mathematical operations on date/time values does not usually produce the kind of result you are expecting.
02:00 (2 AM) is represented as 0.083333333333, and 01:00 (1 AM) is represented as 0.041666666667. You are subtracting 2 AM from 1 AM, expecting it to subtract 2 hours to produce 11 PM (which is represented as 0.958333333333333). Subtracting 0.083333333333 from 0.041666666667 produces -0.041666666667. Ignoring the integral portion (the date), the fractional portion is a positive value from 0.0 (midnight), so -0.041666666667 is equivilent to 0.041666666667, which is 1 AM.
In order for your subtraction to work correctly, the starting time needs a positive integral portion (date) attached to it so the result contains the correct fractional portion, eg:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TTime t = (1.0 + StrToTime("01:00")) - StrToTime("02:00");
// (1.0 + 0.041666666667) - 0.083333333333
// = 1.041666666667 - 0.083333333333
// = 0.95833333333
ShowMessage(t.TimeString());
}

Related

Informix FROM_UNIXTIME alternative

I was searching for a way to group data by interval (ex: every 30 minutes) using the date defined in that table, so i need to convert that date time to milliseconds so that i can divide it by the interval i need like in this query
SELECT FLOOR(UNIX_TIMESTAMP(timestamp)/(15 * 60 * 1000)) AS timekey
FROM table
GROUP BY timekey;
This query is running perfectly on SQL Server but on informix it's giving me the error
Routine (unix_timestamp) can not be resolved.
As it's not defined in IBM Informix server.
So i need a direct way to get epoch unix time from timestamp DATETIME YEAR TO FRACTION(3) column in IBM informix server like 'UNIX_TIMESTAMP' in SQL server.
If the timestamp column is of type DATETIME YEAR TO SECOND or similar, then you can convert it to a DECIMAL(18,5) number of seconds since the Unix Epoch, aka 1970-01-01 00:00:00Z (UTC; time zone offset +00:00) using a procedure such as this:
{
# "#(#)$Id: tounixtime.spl,v 1.6 2002/09/25 18:10:48 jleffler Exp $"
#
# Stored procedure TO_UNIX_TIME written by Jonathan Leffler (previously
# jleffler#informix.com and now jleffler#us.ibm.com). Includes fix for
# bug reported by Tsutomu Ogiwara <Tsutomu.Ogiwara#ctc-g.co.jp> on
# 2001-07-13. Previous version used DATETIME(0) SECOND TO SECOND
# instead of DATETIME(0:0:0) HOUR TO SECOND, and when the calculation
# extended the shorter constant to DATETIME HOUR TO SECOND, it added the
# current hour and minute fields, as documented in the Informix Guide to
# SQL: Syntax manual under EXTEND in the section on 'Expression'.
# Amended 2002-08-23 to handle 'eternity' and annotated more thoroughly.
# Amended 2002-09-25 to handle fractional seconds, as companion to the
# new stored procedure FROM_UNIX_TIME().
#
# If you run this procedure with no arguments (use the default), you
# need to worry about the time zone the database server is using because
# the value of CURRENT is determined by that, and you need to compensate
# for it if you are using a different time zone.
#
# Note that this version works for dates after 2001-09-09 when the
# interval between 1970-01-01 00:00:00+00:00 and current exceeds the
# range of INTERVAL SECOND(9) TO SECOND. Returning DECIMAL(18,5) allows
# it to work for all valid datetime values including fractional seconds.
# In the UTC time zone, the 'Unix time' of 9999-12-31 23:59:59 is
# 253402300799 (12 digits); the equivalent for 0001-01-01 00:00:00 is
# -62135596800 (11 digits). Both these values are unrepresentable in
# 32-bit integers, of course, so most Unix systems won't handle this
# range, and the so-called 'Proleptic Gregorian Calendar' used to
# calculate the dates ignores locale-dependent details such as the loss
# of days that occurred during the switch between the Julian and
# Gregorian calendar, but those are minutiae that most people can ignore
# most of the time.
}
CREATE PROCEDURE to_unix_time(d DATETIME YEAR TO FRACTION(5)
DEFAULT CURRENT YEAR TO FRACTION(5))
RETURNING DECIMAL(18,5);
DEFINE n DECIMAL(18,5);
DEFINE i1 INTERVAL DAY(9) TO DAY;
DEFINE i2 INTERVAL SECOND(6) TO FRACTION(5);
DEFINE s1 CHAR(15);
DEFINE s2 CHAR(15);
LET i1 = EXTEND(d, YEAR TO DAY) - DATETIME(1970-01-01) YEAR TO DAY;
LET s1 = i1;
LET i2 = EXTEND(d, HOUR TO FRACTION(5)) -
DATETIME(00:00:00.00000) HOUR TO FRACTION(5);
LET s2 = i2;
LET n = s1 * (24 * 60 * 60) + s2;
RETURN n;
END PROCEDURE;
Some of the commentary about email addresses is no longer valid – things have changed in the decade and a half since I wrote this.

Java 8 - ChronoUnit.MONTHS.between(fromDate,toDate) not working as expected

I need to find the no. of months between 2 dates, both months inclusive. I am using ChronoUnit.Months.between, but am getting unexpected results.
Code works for : Jan 31 - July 31
Fails for: Jan 31 - June 30
CODE THAT FAILS:
import java.time.LocalDate;
import static java.time.temporal.ChronoUnit.MONTHS;
public class HelloWorld{
public static void main(String []args){
LocalDate startDate=LocalDate.of(2018,01,31);
LocalDate endDate=LocalDate.of(2018,6,30);
//Both dates inclusive, hence adding 1
long noOfMonths = (MONTHS.between(startDate,endDate)) + 1L;
System.out.println(" ********* No. of months between the two dates : " + noOfMonths);
}
}
Expected: 6 (Jan, Feb, Mar, Apr, May, Jun)
Actual: 5
Code that works:
import java.time.LocalDate;
import static java.time.temporal.ChronoUnit.MONTHS;
public class HelloWorld{
public static void main(String []args){
LocalDate startDate=LocalDate.of(2018,01,31);
LocalDate endDate=LocalDate.of(2018,7,31);
//Both dates inclusive, hence adding 1
long noOfMonths = (MONTHS.between(startDate,endDate)) + 1L;
System.out.println(" ********* No. of months between the two dates : " + noOfMonths);
}
}
Expected: 7 (Jan, Feb, Mar, Apr, May, Jun,July)
Actual: 7
Do you see the same behaviour? Is there any alternate way of doing this?
Thanks
Half-Open
The other two Answers by davidxxx and by Ole V.V. are both correct and informative.
I want to add about an alternative approach commonly used in date-time work for defining a span of time: Half-Open. In Half-Open approach, the beginning is inclusive while the ending is exclusive. So the months of the first half of the year (Jan, Feb, Mar, Apr, and Jun) are tracked as starting on January 1 and running up to, but not including, July 1.
Sometimes we intuitively use this approach in our daily life. For example, if a classroom of children breaks for lunch from 12:00 noon to 1 PM, the students are expected to be in their seats before the bell strikes at 1 PM. Lunch break runs up to, but does not include, 1 PM.
I believe you will find consistent use of the Half-Open approach makes your code easier to read, debug, and maintain.
The modern java.time classes use this approach in defining a span of time.
LocalDateRange
The Answer by Ole V.V. wisely suggests you look at YearMonth class to help your work.
Another helpful class is from the ThreeTen-Extra project: org.threeten.extra.LocalDateRange. You can represent your entire date range in a single object.
You can instantiate with a start date and a Period of six months.
LocalDateRange ldr = LocalDateRange.of(
LocalDate.of( 2018 , Month.JANUARY , 1 ) ,
Period.ofMonths( 6 )
) ;
Or specify start and stop dates.
LocalDateRange ldr = LocalDateRange.of(
LocalDate.of( 2018 , Month.JANUARY , 1 ) ,
LocalDate.of( 2018 , Month.JULY , 1 ) // Half-open.
) ;
While I don't recommend it, if you insist on using the Fully-Closed approach where beginning and ending are both inclusive, the LocalDateRange does offer LocalDateRange.ofClosed().
LocalDateRange ldr = LocalDateRange.ofClosed( // `ofClosed` vs `of`.
LocalDate.of( 2018 , Month.JANUARY , 1 ) ,
YearMonth( 2018 , Month.JUNE ).atEndOfMonth() // Fully-closed.
) ;
You can get a count of months from a LocalDateRange via the Period class.
LocalDateRange ldr = LocalDateRange.of(
LocalDate.of( 2018 , Month.JANUARY , 1 ) ,
Period.ofMonths( 6 )
) ;
Period p = ldr.toPeriod() ;
long totalMonths = p.toTotalMonths() ; // 6
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
davidxxx in the other answer has already explained why your code gave an unexpected result. Allow me to add that if you’re interested in months rather than dates, the YearMonth class is the good and correct one for you to use:
YearMonth startMonth = YearMonth.of(2018, Month.JANUARY);
YearMonth endMonth = YearMonth.of(2018, Month.JUNE);
// Both months inclusive, hence adding 1
long noOfMonths = ChronoUnit.MONTHS.between(startMonth, endMonth) + 1;
System.out.println(" ********* No. of months between the two months (inclusive): " + noOfMonths);
Output:
********* No. of months between the two months (inclusive): 6
This obviously also eliminates the problems coming from months having unequal lengths.
If you already got LocalDate objects, it’s probably worth converting:
LocalDate startDate = LocalDate.of(2018, Month.JANUARY, 31);
YearMonth startMonth = YearMonth.from(startDate);
As an aside, do not use two-digit 01 for a month. For January it works, but neither 08 nor 09 will work for August or September, so it’s a bad habit to acquire. Java (and many other languages) understand numbers beginning with 0 as octal numbers.
In terms of calendar, your question is understandable : the two comparisons represent 1 complete month.
But java.time.temporal.ChronoUnit.between doesn't reason in this way but in terms of complete units.
And the result is expected according to its javadoc :
The calculation returns a whole number, representing the number of
complete units between the two temporals. For example, the amount in
hours between the times 11:30 and 13:29 will only be one hour as it is
one minute short of two hours.
The LocalDate.until javadoc that is used under the hood by ChronoUnit.between() is more explicit for your case and also gives an interesting example about between() used with MONTHS as TemporalUnit:
The calculation returns a whole number, representing the number of
complete units between the two dates. For example, the amount in
months between 2012-06-15 and 2012-08-14 will only be one month as it
is one day short of two months.
In your working example :
LocalDate startDate=LocalDate.of(2018,01,31);
LocalDate endDate=LocalDate.of(2018,7,31);
long noOfMonths = MONTHS.between(startDate,endDate);
You have 31 days of month / 31 days of month, on 6 months => 6 months.
In your failing example :
LocalDate startDate=LocalDate.of(2018,01,31);
LocalDate endDate=LocalDate.of(2018,6,30);
long noOfMonths = MONTHS.between(startDate,endDate);
You have 30 days of month / 31 days of month, on 5 months
=> 4 months + 1 month short of 1 day <=> 4 months (rounded).
If you would write something like :
LocalDate startDate=LocalDate.of(2018,01,30);
LocalDate endDate=LocalDate.of(2018,6,30);
long noOfMonths = MONTHS.between(startDate,endDate);
You would have 30 days of month / 30 days of month, on 5 months => 5 months .
About your question :
Is there any alternate way of doing this?
The most simple : set the day of month to 1 or to any same number in both dates.
If it is not suitable for your requirement, you could check if the two dates are the last day of their current month, in this case, set it to the same month value.
You could write something like :
int lastMonthStart = startDate.getMonth()
.length(startDate.isLeapYear());
int lastMonthEnd = endDate.getMonth()
.length(endDate.isLeapYear());
if (startDate.getDayOfMonth() == lastMonthStart && endDate.getDayOfMonth() == lastMonthEnd) {
startDate = startDate.withDayOfMonth(1);
endDate = endDate.withDayOfMonth(1);
}
Other solution:
int getInclusiveMonthsDiff(LocalDate startDate, LocalDate endDate) {
return (endDate.monthValue + endDate.year * 12) - (startDate.monthValue + startDate.year * 12) + 1
}

Descriptive statistics of time variables

I want to compute simple descriptive statistics (mean, etc) of times when people go to bed. I ran into two problems. The original data comes from an Excel file in which just the time that people went to bed, were typed in - in 24 hrs format. My problem is that r so far doesn't recognizes if people went to bed at 1.00 am the next day. Meaning that a person who went to bed at 10 pm is 3 hrs apart from the one at 1.00 am (and not 21 hrs).
In my dataframe the variable in_bed is a POSIXct format so I thought to apply an if-function telling that if the time is before 12:00 than I want to add 24 hrs.
My function is:
Patr$in_bed <- if(Patr$in_bed <= ) {
Patr$in_bed + 24*60*60
}
My data frame looks like this
in_bed
1 1899-12-30 22:13:00
2 1899-12-30 23:44:00
3 1899-12-30 00:08:00
If I run my function my variable gets deleted and the following error message gets printed:
Warning message:
In if (Patr$in_bed < "1899-12-30 12:00") { :
the condition has length > 1 and only the first element will be used
What do I do wrong or does anyone has a better idea? And can I run commands such as mean on variables in POSIXct format and if not how do I do it?
When you compare Patr$in_bed (vector) and "1899-12-30 12:00" (single value), you get a logical vector. But the IF statement requires a single logical, thus it generates a warning and consider only the first element of the vector.
You can try :
Patr$in_bed <- Patr$in_bed + 24*60*60 * (Patr$in_bed < as.POSIXct("1899-12-30 12:00"))
Explanations : the comparison in the parenthesis will return a logical vector, which will be converted to integer (0 for FALSE and 1 for TRUE). Then the dates for which the statement is true will have +24*60*60, and the others dates will have +0.
But since the POSIXct format includes the date, I don't see the purpose of adding 24 hrs. For instance,
as.POSIXct("1899-12-31 01:00:00") - as.POSIXct("1899-12-30 22:00:00")
returns a time difference of 3 hours, not 21.
To answer your last question, yes you can compute the mean of a POSIXct vector, simply with :
mean(Patr$in_bed)
Hope it helps,
Jérémy

Converting a 19 digits time stamp to a real time (from .zvi file format)

After a long day of research,
Is anybody knows how to convert a 19 digits time stamp from the metadata of .zvi file (produce by axiovision, Zeiss) to a real time format ? (The output probably includes milliseconds)
An example time-stamp is: 4675873294709522577
Thanks !
Arnon
Matlab solution:
The main issue is not the x2mdate conversion (which simply adds the number of days between the year zero, when Matlab starts counting, and the year 1900, when Excel/zvi starts counting), but the same class issue as described above. This conversion to double can be done with typecast in Matlab:
myZVI = 4675946358764751269;
timestampDouble = typecast(int64(myZVI),'double');
myTime = datestr(timestampDouble + 693960, 'dd-mmm-yyyy HH:MM:SS.FFF');
693960 is the number of days between year zero and 1900; if you don't need an absolute date but just the difference between two timestamps, you don't even need this; for instance the interval between two of my video frames can be calculated like this:
myZVI2 = 4675946358764826427;
timestampDouble2 = typecast(int64(myZVI2),'double');
myTimeDifference = datestr(timestampDouble2 - timestampDouble,'SS.FFF');
hope this helps:-)
This is a Microsoft OLE Automation Date. But you've read it as a 64-bit long integer instead of the 64-bit double that it should be.
You didn't specify a language, so I will pick C#:
long l = 4675873294709522577L;
byte[] b = BitConverter.GetBytes(l);
double d = BitConverter.ToDouble(b, 0);
Debug.WriteLine(d); // 41039.901598693
DateTime dt = DateTime.FromOADate(d);
Debug.WriteLine(dt); // 5/10/2012 9:38:18 PM
More information in this thread.
An OLE Automation Date is basically the number of whole 24-hour days since 1/1/1900 without any particular time zone reference.

Calculating duration when you have hours, minutes, seconds, and milliseconds

I am writing a program in Fortran and I need a way of calculating the duration of the program down to milliseconds. I have been using the function "date_and_time", which leaves me with an array containing the system's time in hours, minutes, seconds, and milliseconds.
I believe that I can call this function at the start of my program to store the current time, then call the function again at the end of my program to store the latest time. But after that, how would I computer the duration? I tried just subtracting the values, but the milliseconds reset when one second passes, just like the seconds reset when one minute passes. How would be best way to approach this be?
Here is the program:
PROGRAM TEST_TIME_AND_DATE
INTEGER I
REAL J
INTEGER TIME_A(8), TIME_B(8)
CALL DATE_AND_TIME(VALUES=TIME_A)
PRINT '(8I5))', TIME_A
DO I = 0, 400000000
J = I * I - J
END DO
CALL DATE_AND_TIME(VALUES=TIME_B)
print '(8I5))', TIME_B
END PROGRAM TEST_TIME_AND_DATE
And here is the result:
2011 6 11 -300 9 14 49 304
2011 6 11 -300 9 14 50 688
I'm not sure what to do here, thanks.
If you want elapsed clock time, it would be simpler to use the intrinsic procedure system_clock since it provides a single time-value output. (There are additional arguments to provide information about the procedure, which is why it is a procedure instead of a function.) See, for example, http://gcc.gnu.org/onlinedocs/gfortran/SYSTEM_005fCLOCK.html. If you want to time the CPU usage, then use cpu_time. For either, two calls, at the start and end of the program, then a simple difference. You can use the COUNT_RATE argument to convert to integer count of time into seconds.
You can subtract the numbers, then convert everything into milliseconds and sum up the ms, sec in ms, min in ms, hrs in ms, ...
In your case this would be
0 + 0 + 0 + 0 + 0 + 1*1000 + 384 = 1384 [ms]
This approach works fine also with overflows since a positive number in a left-more column outweights negative numbers if they are all converted to the same basis. E.g. 0:58.000 to 1:02.200 yields
1 * 60000 + (-56) * 1000 + 200 = 4200
Please note that this does work up to days but not with months since they do not share a common length.
You could calculate the offset from some starting time (Jan 1, 1970 for UNIX) in seconds or milliseconds. The difference in those numbers is your elapsed time.
(2011 - 1970) * (number of seconds in a year) +
(month of the year - 1) * (number of seconds in a month) +
(day of the month - 1) * (number of seconds in a day) +
( ... )

Resources