Reputation: 141
I'm trying to sort my arrayList
by date. I stored the date on Firebase each time I receive a notification and is retrieved from there. I'm using Collections.sort
but I don't know how to implement onto my codes as my date format starts with a number in a string format like "12 Jul 2017 at 12:00am".
I've seen some examples of this on stackoverflow but I don't know how to make it work in my case. I will post screenshots and my codes below.
The dates are not sorted.
NotificationFragment.java
public class NotificationFragment extends Fragment {
prepareNotification1();
sortDate();
return v;
}
private void prepareNotification1() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String userID = user.getUid();
mRef.child("customers").child(userID).child("Notification").addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Notification menu = dataSnapshot.getValue(Notification.class);
notificationList.add(menu);
mAdapter.notifyDataSetChanged();
}
});
}
public void sortDate() {
Collections.sort(notificationList, new Comparator<Notification>() {
@Override
public int compare(Notification lhs, Notification rhs) {
return lhs.getDate().compareTo(rhs.getDate());
}
});
mAdapter = new NotificationAdapter(getContext(), notificationList);
mRecyclerView.setAdapter(mAdapter);
}
}
MyFirebaseMessagingService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Calendar cal = Calendar.getInstance();
String currentDateTimeString = DateFormat.getDateInstance().format(new Date());
SimpleDateFormat df = new SimpleDateFormat("hh:mm a");
String currentTime = df.format(cal.getTime());
String notificationTime = currentDateTimeString + " at " + currentTime;
Notification newNotification = new Notification(remoteMessage.getData().get("body"), notificationTime);
mRef.child("customers").child(userID).child("Notification").push().setValue(newNotification);
}
Notification.java
public class Notification {
private String message;
private String date;
public Notification(){
}
public Notification(String message, String date){
this.message = message;
this.date = date;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Upvotes: 5
Views: 21270
Reputation: 79085
You can simply parse the date-time strings into LocalDateTime
and perform a natural sorting.
Using Stream
:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("d MMM u 'at' h:m a", Locale.UK);
Stream.of(
"10 Jul 2017 at 10:59 pm",
"10 Jul 2017 at 10:59 pm",
"11 Jul 2017 at 11:15 pm",
"9 Jul 2017 at 11:15 pm"
)
.map(s -> LocalDateTime.parse(s, dtf))
.sorted()
.forEach(dt -> System.out.println(dtf.format(dt)));
}
}
Output:
9 Jul 2017 at 11:15 pm
10 Jul 2017 at 10:59 pm
10 Jul 2017 at 10:59 pm
11 Jul 2017 at 11:15 pm
Non-Stream
solution:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("d MMM u 'at' h:m a", Locale.UK);
List<LocalDateTime> listLdt = new ArrayList<>();
List<String> listDtStr =
Arrays.asList(
"10 Jul 2017 at 10:59 pm",
"10 Jul 2017 at 10:59 pm",
"11 Jul 2017 at 11:15 pm",
"9 Jul 2017 at 11:15 pm"
);
// Add the strings, parsed into LocalDateTime, to listLdt
for(String s: listDtStr) {
listLdt.add(LocalDateTime.parse(s, dtf));
}
// Sort listLdt
Collections.sort(listLdt);
// Display
for(LocalDateTime ldt: listLdt) {
System.out.println(ldt.format(dtf));
}
}
}
Output:
9 Jul 2017 at 11:15 pm
10 Jul 2017 at 10:59 pm
10 Jul 2017 at 10:59 pm
11 Jul 2017 at 11:15 pm
Learn more about the modern date-time API from Trail: Date Time.
Using legacy date-time API:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
final SimpleDateFormat sdf = new SimpleDateFormat("d MMM u 'at' h:m a", Locale.UK);
List<Date> listDate = new ArrayList<>();
List<String> listDtStr =
Arrays.asList(
"10 Jul 2017 at 10:59 pm",
"10 Jul 2017 at 10:59 pm",
"11 Jul 2017 at 11:15 pm",
"9 Jul 2017 at 11:15 pm"
);
// Add the strings, parsed into LocalDateTime, to listDate
for(String s: listDtStr) {
listDate.add(sdf.parse(s));
}
// Sort listDate
Collections.sort(listDate);
// Display
for(Date date: listDate) {
System.out.println(sdf.format(date));
}
}
}
Output:
9 Jul 4 at 11:15 pm
10 Jul 5 at 10:59 pm
10 Jul 5 at 10:59 pm
11 Jul 6 at 11:15 pm
Note: The java.util
date-time API and their formatting API, SimpleDateFormat
are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API* .
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Upvotes: 2
Reputation: 1756
In my answer I will use an ArrayList
for debts named debtsArrayList
. This answer will show how to sort an ArrayList
with objects by date
in both ascending
and descending
order.
First create a SortComparator
class to hold the functions to sort by date in ascending
and descending
order.
public class SortComparator {
/**
* Class to sort list by Date
*/
public static class SortBy_Date {
/**
* Class to sort list by Date in ascending order
*/
public static class Ascending implements Comparator<JB_Debts> {
@Override
public int compare(JB_Debts jbDebts1, JB_Debts jbDebts2) {
// Create DateFormat
DateFormat dateFormat = DateFormat.getDateInstance(
DateFormat.FULL, Locale.ENGLISH);
// Catch Parse errors
try {
// Parse dates
Date date1 = dateFormat.parse(jbDebts1.getDate());
Date date2 = dateFormat.parse(jbDebts2.getDate());
// Check if dates are null
if ((date1 != null) && (date2 != null)) {
// Ascending
return (date1.getTime() > date2.getTime() ? 1 : -1);
} else {
return 0; // Return 0 to leave it at current index
}
} catch (Exception exception) {
exception.printStackTrace();
}
return 0;
}
}
/**
* Class to sort list by Date in descending order
*/
public static class Descending implements Comparator<JB_Debts> {
@Override
public int compare(JB_Debts jbDebts1, JB_Debts jbDebts2) {
// Create DateFormat
DateFormat dateFormat = DateFormat.getDateInstance(
DateFormat.FULL, Locale.ENGLISH);
// Catch Parse and NullPointerExceptions
try {
// Parse dates
Date date1 = dateFormat.parse(jbDebts1.getDate());
Date date2 = dateFormat.parse(jbDebts2.getDate());
// Check if dates are null
if ((date1 != null) && (date2 != null)) {
// Descending
return (date1.getTime() > date2.getTime() ? -1 : 1);
} else {
return 0; // Return 0 to leave it at current index
}
} catch (Exception exception) {
exception.printStackTrace();
}
return 0;
}
}
}
}
In my example I am using an ArrayList with objects ArrayList<JB_Debts>
where JB_Debts
is my Java bean class with getter and setter methods.
public class JB_Debts {
private String date; // Our date string
/**
* Default constructor
*/
public JB_Debts2() {
}
/**
* Function to get date
*/
public String getDate() {
return date;
}
/**
* Function to set date
*
* @param date - Date
*/
public void setDate(String date) {
this.date = date;
}
}
We will then use this class with Java collections to sort our ArrayList<JB_Debts> with objects based on Date in ascending and descending order.
// Create ArrayList
ArrayList<JB_Debts> debtsArrayList = new ArrayList();
Collections.sort(debtsArrayList,
new SortComparator.SortBy_Date.Ascending());
Collections.sort(debtsArrayList,
new SortComparator.SortBy_Date.Descending());
Note
Please note that I stored the date in my ArrayList as a string. To sort them, I parsed the string to date as below:
// Create DateFormat with Locale
DateFormat dateFormat = DateFormat.getDateInstance(
DateFormat.FULL, Locale.ENGLISH);
// Create DateFormat without Locale
DateFormat dateFormat = DateFormat.getDateInstance(
DateFormat.FULL);
You can replace the DateFormat.FULL
with a date format of your choice e.g. "dd/MM/yyyy hh:mm a"
which will then look as below:
// Create DateFormat with Locale
DateFormat dateFormat = new SimpleDateFormat(
"dd/MM/yyyy hh:mm a", Locale.ENGLISH);
// Create DateFormat without Locale
DateFormat dateFormat = new SimpleDateFormat(
"dd/MM/yyyy hh:mm a");
I hope this helps
Upvotes: 2
Reputation: 2142
Instead of setting date like following in Notification model.
String notificationTime = currentDateTimeString + " at " + currentTime;
you can save time as System.currentTimeinMillis(); and while displaying then parse it to Date as following
DateFormat f = new SimpleDateFormat("dd/MM/yyyy hh:mm a");
f.parse(timeStamp);
Upvotes: 0
Reputation: 163
As I understand, Notification.getDate() returns String value. So, use
public static Date toDate(String value) throws ParseException {
DateFormat format = new SimpleDateFormat("d MMMM yyyy 'at' HH:mm'am'", Locale.ENGLISH);
return format.parse(value);
}
this method to det Date from your String. Just get two dates and use Date.compareTo method.
date1 = toDate(lhs.getDate());
date2 = toDate(rhs.getDate());
date1.compareTo(date2);
Upvotes: 1
Reputation: 3151
Consider storing the date in Notification
as a long
(unix time) or a Date
(LocalDateTime
if you're using Java 8 support) and formatting it as a String only when displaying it to the UI.
Upvotes: 5
Reputation: 3349
Do sorting after parsing the date.
Collections.sort(notificationList, new Comparator<Notification>() {
DateFormat f = new SimpleDateFormat("dd/MM/yyyy '@'hh:mm a");
@Override
public int compare(Notification lhs, Notification rhs) {
try {
return f.parse(lhs.getDate()).compareTo(f.parse(rhs.getDate()));
} catch (ParseException e) {
throw new IllegalArgumentException(e);
}
}
})
If your date is in some other format, write the DateFormat accordingly.
Upvotes: 11