Repository: microsoft/gctoolkit
File: core/api/src/main/java/com/microsoft/gctoolkit/time/DateTimeStamp.java (Java)

Code before:
     * Return the difference between this time stamp, and the time stamp of
     * the other DateTimeStamp.
     * @param dateTimeStamp The other {@code DateTimeStamp}
     * @return The difference between this time stamp, and the time stamp
     * of the other DateTimeStamp.
     */
    public double minus(DateTimeStamp dateTimeStamp) {
        return timeStamp - dateTimeStamp.timeStamp;
    }

    /**
     * Return the difference between time stamps, converted to minutes.
     * This is a convenience method for {@code this.minus(dateTimeStamp) / 60.0}.
     * @param dateTimeStamp The other {@code DateTimeStamp}
     * @return The difference between time stamps, converted to minutes.
     */
    public double timeSpanInMinutes(DateTimeStamp dateTimeStamp) {
        return this.minus(dateTimeStamp) / 60.0d;
    }

    @Override
    public int compareTo(DateTimeStamp dateTimeStamp) {
        return  comparator.compare(this,dateTimeStamp);
    }
    private static  Comparator<DateTimeStamp> getComparator(){
        return nullsLast(comparing(DateTimeStamp::getDateTime));
    }
}


Review comment (bug):
DateTimeStamp is kind of a tricky thing because it depends on the log file flags. Sometimes, there is no ISO date/time in the log. Sometimes there isn't even a time stamp (which represents milliseconds since the start of the JVM). Indeed, most of the time we only care about the time stamp. 

The way this class is written and used is to try to ensure there is always a timeStamp. It is possible that timeStamp could be NaN, or less than zero - neither of which make sense and point to a bug in the code that calls the constructor. 

So you may or may not have a dateTime, but you should always have a timeStamp >= 0. One possible way to do this compare is to compare the dateTime (if not null) and if they are the same, then compare the timeStamp. Another possible way would be to add the timeStamp value to the dateTime (if not null) and compare that. 



Code after:
        return add(-offsetInDecimalSeconds);
    }

    /**
     * Return the difference between this time stamp, and the time stamp of
     * the other DateTimeStamp.
     * @param dateTimeStamp The other {@code DateTimeStamp}
     * @return The difference between this time stamp, and the time stamp
     * of the other DateTimeStamp.
     */
    public double minus(DateTimeStamp dateTimeStamp) {
        return timeStamp - dateTimeStamp.timeStamp;
    }

    /**
     * Return the difference between time stamps, converted to minutes.
     * This is a convenience method for {@code this.minus(dateTimeStamp) / 60.0}.
     * @param dateTimeStamp The other {@code DateTimeStamp}
     * @return The difference between time stamps, converted to minutes.
     */
    public double timeSpanInMinutes(DateTimeStamp dateTimeStamp) {
        return this.minus(dateTimeStamp) / 60.0d;
    }

    /**
     * It will compare date time first, if both are equals then compare timestamp value,
     * For Null date time  considered to be last entry.
     * @param dateTimeStamp - other object to compared
     * @return  a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object
     */
    @Override
    public int compareTo(DateTimeStamp dateTimeStamp) {

        return  comparator.compare(this,dateTimeStamp);
    }

    private static  Comparator<DateTimeStamp> getComparator(){
        // compare with dateTime field, if null then it will go to last
        return nullsLast((o1, o2) -> {
            Comparator<DateTimeStamp> dateTimeStampComparator = compareDateTimeStamp(o1, o2);
            return dateTimeStampComparator.compare(o1,o2);
        });
    }

    private static Comparator<DateTimeStamp> compareDateTimeStamp(DateTimeStamp o1, DateTimeStamp o2) {
        if (o1.getDateTime() == null || o2.getDateTime() == null) {
            //if any of value is null then check timestamp
            return comparing(DateTimeStamp::getTimeStamp);
        } else {
            // means both values for date time are present, then compare datetime and timestamp.
            return comparing(DateTimeStamp::getDateTime).thenComparing(DateTimeStamp::getTimeStamp);