timevalue and if conflict

Copper Contributor

Hi team, I am using timevalue() function to retrieve the time from a text string. This works well. The result is a time-format hh:mm:ss . Then I am comparing the result with a fixed "time" (also hh:mm:ss) per if() formula. problem is, that sometimes recognizes the mapping correct (true), sometimes not (False). even if the same numbers are compared. what can I do ? example: the text "2021-01-02 04:00:00" delivers 04:00:00 (time format) as result from timevalue(2021-01-02 04:00:00). The if() function comparing that result with the fixed time "04:00:00" (time format). In another case with 02:00:00 this works well. It appears this is a random behavior, for some "times" it is true , for others not, even if the it is the same numbers mappin. what can I do ? 

5 Replies
maybe one point to add: when replacing the result of timevalue() by simply edition the number, then if() works perfectly. So in my case timevalue returned "04:00:00" in time format, which was not TRUEd in an if() comparison with "04:00:00" cell (time-format). If replacing the timevalue result by simple editing "04:00:00" (time-fomrat), then the if() results in TRUE. Any idea ?

@EBi2022 

Let's say the string is in A1 and the time in B1.

Round the result of TIMEVALUE to 1 second:

 

=MROUND(TIMEVALUE(A1),TIME(0,0,1))=B1

 

(I'll wait for @Joe User to explain, and possibly correct it)

@EBi2022 

 

In essence, you are saying:

TIMEVALUE("2021-01-02 4:00") = TIMEVALUE("4:00") returns FALSE (!).

 

(We can replace TIMEVALUE("4:00") with TIME(4,0,0) or --"4:00" or 4:00 entered into a cell.)

 

The problem is the binary approximation of the time value in both cases.  We can demonstrate it as follows:

 

JoeUser_0-1643497849680.png

 

The strings in column B are created with formulas of the form =A2&"", which displays the decimal representation of the internal binary value, rounded to up to 15 signifcant digits.

 

Note the difference in the last 4 digits.  That is why the comparison fails.

 

It might help to understand how Excel stores time as a number.  Dates are an integer value, namely the number of days after 12/31/1899.  So, 1/1/1900 is 1.  2021-01-02 is 44198 or 44228, depending on whether that is Jan 2 or Feb 1.  (And I am assuming a default Excel for Windows date system.  The integer value is different for a default Excel for Mac.)  Time is a fraction of 1 day (24 hr).  So 4:00 is the fraction 4/24, which is 1/6 = 0.666666666666667, rounded.

 

But Excel stores numbers in binary (64-bit floating-point), which has a limited binary precision (the sum of 53 consecutive powers of 2, called "bits").  Most decimal fractions cannot be represented exactly in binary; they must be approximated.  And the approximation of a particular decimal fraction (e.g. 1/6) might vary, depending on the magnitude of the number.  That is why, for example, 10.01 - 10 = 0.01 returns FALSE (!).

 

The same thing is happening here.  For the time 4:00, Excel can use all 53 bits to represent the decimal fraction.  But for the date/time 2021-01-02 4:00, some of those bits must be used to represent the date (integer part).  Consequently, there are fewer bits to represent the decimal fraction.  So, we lose precision.

 

Surprisingly (to me), TIMEVALUE simply extracts the binary fraction.  It is equivalent to MOD(TIMEVALUE(...), 1).  That is unwise because the binary fraction of the date/time is often not the same as the binary approximation of the time alone.

 

We can correct for this in several ways.  And frankly, I'm surprised that TIMEVALUE does not make the correction automagically.  I had assumed it does.  (Thanks for the education.)

 

One solution:  use TEXT instead of TIMEVALUE.  Namely:

 

--TEXT("2021-01-02 4:00:00", "h:m:s")

 

The double-negate converts the text result to a numeric result.  But there is nothing sacrosanct about "--".  Some people prefer 0+TEXT(...) or 1*TEXT(...).  Any arithmetic operation will suffice for the conversion.

 

@Hans Vogelaar  wrote: ``=MROUND(TIMEVALUE(A1),TIME(0,0,1))=B1``

 

It is unwise to use MROUND where the second parameter has a decimal fraction (other than a power of 2).

 

For example, if A1 is ="2021-01-02 21:55" and B1 is the numeric time 21:55, that MROUND formula returns FALSE (!).

 

The reason is essentially the same as I explained in my response to @EBi2022 .  TIMEVALUE(A1) returns the numeric value 0.913194444445253, rounded, whereas 21:55 is the numeric value 0.913194444444445, rounded.

@Joe User and @Hans Vogelaar: Thanks a lot for your thoughts and explanations. This all sounds reasonable when you think about it. However, same as Joe_User explained, I am bit surprised rounding is not done by timevalue(). Also it surprises me that I am encountering this "issue" only now as I am using timevalue() more often. A reason for this is that I use the timevalue() result to map it with a range (e.g. is the result >4:00 AND <=5:00), so it is not becoming obvious immediately.

I am now using "--TEXT(<text>;"hh:mm:ss")" as you suggested and it works well !

 

Thanks again for your help and support on such short notice !