It is possible to write a Comparable wrapper class that can work with various SObject types and fields:
public class DateFieldComparable implements Comparable {
private SObject sob;
private SObjectField field;
public DateFieldComparable(SObject sob, SObjectField field) {
this.sob = sob;
this.field = field;
}
public Integer compareTo(Object o) {
DateFieldComparable that = (DateFieldComparable) o;
Date thisValue = (Date) this.sob.get(field);
Date thatValue = (Date) that.sob.get(that.field);
if (thisValue < thatValue) return -1;
else if (thisValue > thatValue) return 1;
else return 0;
}
public SObject getSObject() {
return sob;
}
}
that can then be used like this:
// Wrap and sort
DateFieldComparable[] fcs = new DateFieldComparable[] {};
for (Project__c p : projects) {
fcs.add(new DateFieldComparable(p, Project__c.MyDateField__c));
}
for (assignment__c : assignments) {
fcs.add(new DateFieldComparable(a, Assignment__c.OtherDateField__c));
}
fcs.sort();
// Pull back out the sorted objects
SObject[] sobs = new SObject[] {};
for (FieldComparable fc : fcs) {
sobs.add(fc.getSObject());
}
This code is using the SObjectField token to represent a field which has the benefit that the compiler checks that the field exists. But if it is more convenient, you can use a string that holds the field API name because there is an SObject.get available for both types.
PS
Changed to a specific data type per sfdcfox's comment.