# Array.Sort() Operator Has Trouble With Return Values Between Zero And One In Lucee CFML 5.3.7.47

As it is **documented**, the `Array.sort()`

method (and `arraySort()`

function), when given an operator to execute, are supposed to return the values `-1`

, `0`

, and `1`

when comparing two values within the collection. Documentation aside, the `.sort()`

method is actually *much more flexible* than that, allowing for *almost any* number to be returned. This is why we can implement our sort operator using math. However, playing fast-and-loose with the return value can result in funky edge-cases, such as accidentally returning a value that falls outside of the `INT`

space. Last week, I ran into yet another such edge-case. Apparently, the `Array.sort()`

operation does not like handling decimal values between `0`

and `1`

, such as `0.345`

in Lucee CFML 5.3.7.47.

To this in action, all we have to do is try using **math** to sort a bunch of decimal values between `0`

and `1`

:

```
<cfscript>
// NOTE: All of these values are less that "1.0" apart.
values = [
0.1,
0.8,
0.5,
0.2,
0.7,
0.4
];
values.sort(
( a, b ) => {
return( a - b ); // Sort ascending.
}
);
for ( value in values ) {
echo( value & "<br />" );
}
</cfscript>
```

Note that I am *attempting* to use "math", `(a - b)`

, to power the sort operation. However, when we run this, we get the following output:

0.1

0.8

0.5

0.2

0.7

0.4

As you can see, the values come back in the *original order* that the array was defined - not in a sorted order. I assume that this is because any value between `-1`

and `1`

- **excluding -1 and 1** - tell the underlying algorithm that the values are

*equal*, therefor leaving them in-place.

In my original code, I wasn't actually sorting numbers - I was sorting dates. And, as you may know, **dates can be represented as numbers** in ColdFusion. You can see this by taking a date/time value and multiplying it by `1`

:

`echo( now() * 1 ); // Outputs 44215.279176435186`

This numeric value is the *factional days* since the "ColdFusion zero day", which is `Saturday, December 30, 1899`

. Because of this behavior, you can perform **date math** on date/time objects in ColdFusion by simply adding and subtracting two dates.

In what was an approach that ended-up being "too clever", I was attempting to use this date-math behavior to sort an array of date/time values. Notice that the date/times values in my input array are all less than 24-hours apart:

```
<cfscript>
// NOTE: All of these dates are LESS than 24-hours apart, but are on different days.
dates = [
parseDateTime( "2019-11-27 10:54:01" ),
parseDateTime( "2019-11-26 15:53:17" ),
parseDateTime( "2019-11-27 12:40:29" ),
parseDateTime( "2019-11-26 19:50:17" ),
parseDateTime( "2019-11-27 02:44:16" )
];
// Attempting to use "date math" to sort the dates. When performing raw math on
// date/time values, ColdFusion implicitly converts them to a numeric representation
// of fractional days (this is NOT epoch time). As such, I was ATTEMPTING to return
// the sort indication by simply subtracting one date from another, leaving us with a
// value that was either less-than-zero, zero, or more-than-zero.
dates.sort(
( a, b ) => {
return( b - a ); // Sort descending.
}
);
for ( value in dates ) {
echo( "#value# → as number: #( value * 1 )# <br />" );
}
</cfscript>
```

Since my input dates were all less than 24-hours apart, it means that all of the *fractional day differences* (date math) are less than `1`

. Which, as we saw above, means that ColdFusion won't see them as "different" in the sorting algorithm. As such, when we run this Lucee CFML code, we get the following output:

{ts '2019-11-27 10:54:01'} → as number: 43796.45417824074

{ts '2019-11-26 15:53:17'} → as number: 43795.66200231481

{ts '2019-11-27 12:40:29'} → as number: 43796.52811342593

{ts '2019-11-26 19:50:17'} → as number: 43795.826585648145

{ts '2019-11-27 02:44:16'} → as number: 43796.114074074074

As you can see - just as with our first demo - the values are left in-place. Essentially, the whole sort was a no-op (No Operation) since the differences between all the values were less than `1`

.

To "fix" this behavior, all I had to do was revert back to using the "documented" behaviors of the `Array.sort()`

function:

```
<cfscript>
// Instead of trying to do anything fancy, we're just going to use the SORT() method
// the way it was always documented - by returning -1, 0, and 1.
dates.sort(
( a, b ) => {
if ( a == b ) {
return( 0 );
}
return( ( a < b ) ? 1 : -1 );
}
);
</cfscript>
```

Obviously, all of this "trouble" comes from an attempt to push the limits of what the `.sort()`

method can do. If you just use the method *as documented*, you'll never run into any of these issues. But, it's nice to know where the limits are in Lucee CFML 5.3.7.47.

Want to use code from this post? Check out the license.

## Reader Comments

## Post A Comment — ❤️ I'd Love To Hear From You! ❤️

Post a Comment →