# 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.

## Reader Comments

## Post A Comment

You— Get Out Of My Dreams, Get Into My Blog