I vaguely understand what ChoiceFormat does (it says that it's meant for controlling how singular/plurals work, but CG is using it differently here). I understand that there are two arrays, filelimits and filepart, and that the indexes of the former match up with the indexes in the latter. For example, index 0 of filelimits is 0d and that matches up with index 0 of filepart which is "change {4}". I think the intention is to replace "{6}" in the messageformat with "change {4}" if something is equal to 0d, but I don't know what that something is. Likewise, under different circumstances, "{6}" gets replaced with "open {2} and last {3}". The reason I assume it is "{6}" that gets replaced is only because that would cause the output to match what is in the example given in the conditions file. But I don't actually see in the code how it would know which part gets replaced. But that's about the limit of what I understand. I don't understand why testFormats has a null in it or what that does in this context. And I can't find any non-cryptic explanation (like the Oracle one) about what the setFormats method does. Googling for it mostly returns results for the different setFormat method (without the s at the end). I'm tempted to try and replace the entire formatting section with conditionals. It would be a few more lines but far more readable. I'm not sure if the validation would pass if I did that, though, and if it did not pass I could only get the format code back by resetting the task and then I'd also lose the work I did getting the sorting to work. EDIT: I got it! Solved that part, only to discover that the validation isn't accepting my sort algorithm even though the output appears to be correct. Here is my current process of sorting, with comments explaining my reasoning:
public static void sort(List<Stock> list)
{
    Collections.sort(list, new Comparator<Stock>()
    {
        public int compare(Stock stock1, Stock stock2)
        {
            //first sort by name. The compareTo method for Strings defaults to alphabetical sorting, so I don't think this part requires anything complicated.
            String name1 = (String) stock1.get("name");
            String name2 = (String) stock2.get("name");
            int c = name1.compareTo(name2);
            if(c == 0)
            {
                //if names are equal, then sort by date. It requires us to ignore anything smaller than day, so to do this I created another method dateMinusTime (see below)
                //default date sorting is oldest first, so I set c = to the negative of the compareTo result to sort the other way
                Date date1 = dateMinusTime((Date) stock1.get("date"));
                Date date2 = dateMinusTime((Date) stock2.get("date"));
                c = -date1.compareTo(date2);
                if(c == 0)
                {
                    //if the dates are the same, compare by the change value
                    //For each stock, determine if it has a "change" key, if so use that value, if not use the "close" minus "open".
                    //for some reason when using a double variable, there is no compareTo() method. IDEA would not recognize it. So I did the process there manually
                    //Since doubles default sort by smallest first, and we want largest first, I reversed the result so that if change1 > change 2, it returns -1.
                    double change1, change2;
                    if(stock1.containsKey("change"))
                    {
                        change1 = (double) stock1.get("change");
                    }
                    else
                    {
                        change1 = (double) stock1.get("close") - (double) stock1.get("open");
                    }
                    if(stock2.containsKey("change"))
                    {
                        change2 = (double) stock2.get("change");
                    }
                    else
                    {
                        change2 = (double) stock2.get("close") - (double) stock2.get("open");
                    }
                    if(change1 < change2)
                    {
                        return 1;
                    }
                    if(change1 > change2)
                    {
                        return -1;
                    }
                    return 0;
                }
            }
            return c;
        }

        public Date dateMinusTime(Date input)
        {
            //Simple method I googled up for how to convert a date into one where anything smaller than day is set to 0. If two dates have 0s for all those parts,
            //then comparing them will only consider year, month, and day.
            Calendar cal = Calendar.getInstance();
            cal.setTime(input);
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
            cal.set(Calendar.MILLISECOND, 0);
            return cal.getTime();
        }
    });
}
Also, at this point my issue is not about not knowing how to solve the problem, but about not knowing why it isn't accepting my code that appears to work, so I've looked at the solution. The solution creates a lot more methods than mine, but in studying what it does, it appears to be functionally identical to my code, although their getProfitPercentage method is weird because they multiply by 1000 before returning (because the result of a comparison is an integer, I guess?). It seems wonky and I honestly like my code a lot more than the solution code, except that it won't pass validation.