convert String to Double, pre 3.1

Hi, I have been using the toDouble() function to convert a string to double. However, the toDouble() method is only available from 3.1 and I'd like to add some devices that don't support 3.x.

I found a solution here on the forum and it works in the simulator, by using toFloat().toDouble()

I was just curious to understand if I will get any issues with this conversion (or get a different value as a result). 

Here is a code example to show what I want to do:

var timeString = "1611495355000" // sample time represented as String


//previous solution, works for 3.0 devices:
var sampleTime = new Time.Moment(timeString.toDouble() / 1000);

//new solution, works also for 2.0 devices:
var sampleTime = new Time.Moment(timeString.toFloat().toDouble() / 1000);

thanks in advance

/Fredrik

  • What if you just do toNumber()?   Does timeString need to be a string to begin with?  Where does it come from?

  • If it has to be a string, you could use substring to strip of the last 3 digits (miliseconds), and then it will fit in a Number.

  • In general, I wouldn't use toFloat() (or toDouble()) on an integer, because of floating point errors.

    For example:

    System.println("float: " + "1611495355000".toFloat());

    produces "float:1611495374848.000000"

    And:

    System.println("double: " + "1611495355000".toDouble());

    produces "double:1611495355000.000000"

    It just so happens that a double has enough bits to preserve the original value without introducing errors, but in general that's the kind of thing you don't want to have to worry about.

    In your example, calling toDouble() after toFloat() doesn't help -- you're not gaining any precision that way. May as well just call toFloat() (but then you'll lose information as seen above.)

    Jim's suggestion is probably the simplest solution for this particular case (if your data must be a string in the form of milliseconds), but keep in mind there's an edge case where the string could be 3 chars or less. (Although I'm guessing that's an unlikely or impossible case.)

    None of these solutions handle rounding of milliseconds either. Is it possible for the milliseconds part to be non-0, and in that case, should rounding apply (e.g. should 500 ms round to up 1000)?

    If you have control over the input, it would be easier just to specify the time in seconds, as an integer. Sounds like you might not, though.

  • If you want a generic function to convert a string to long (signed int64) without loss of precision/data, which works on all devices, you can use this. I haven't tested it extensively, and it contains no error-checking for the following conditions:

    • invalid chars (e.g. "."). The function will probably throw an error on most kinds of invalid input.
    • out of bounds values (greater than the max possible signed int64 value, or less than the min possible signed int64 value). If the input value is out of bounds, the converted value will overflow or underflow.

    I did test with the following values, on a simulated FR230:

    -9223372036854775808 (min int64)

    9223372036854775807 (max int64)

    1611495355000 (your value)

    function stringToLong(str) {
        var strLength = str.length();
        if (strLength == 0) { // you may want to handle this edge case a different way
            return null;
        }
    
        var longValue = 0l;
        var sign = 1;
        if (strLength > 0 && str.substring(0, 1).equals("-")) {
            sign = -1;
            str = str.substring(1, strLength);
            strLength--;
        }
        var power = 1l;
        for (var i = 0; i < strLength; i++) {
            longValue += str.substring(strLength - i - 1, strLength - i).toNumber() * power;
            power *= 10;
        }
        return longValue * sign;
    }

  • Hi Jim. The time string comes in a json response from a http server. When I use toNumber() I get a type exception in runtime. 

  • This seems like a very good approach. i will try it out. I really don't need millisecond accuracy. 

  • So it's really not an epoch/unix time, but includes milliseconds.  I'd go with doing a substring to remove the last 3 digits, and then toNumber() should work.  And what you're passing to Time.Mement() is really a Number.  It's the number of seconds since Jan 1, 1970 00:00 UTC

  • yes. Initial testing looks good. Ill go with this approach. Thanks Jim. 

  • It's odd they include ms.  Sites I use always provide a time stamp in seconds

  • Javascript's Date.now() returns the number of milliseconds since the epoch (Jan 1, 1970 00:00:00 UTC).