I got a recyclerView that will populate according to a JSON result using databinding, what i want to do is to check/compare the start date & expired date to see is the "Deals" is expired (if expired a textview with text "DEALS EXPIRED" will appear)
"DealsPageInfo": [
{
"DisplayName": "string",
"StartDate": "2018-04-27T03:06:18.890Z",
"ExpiredDate": "2018-04-27T03:06:18.890Z",
"Url": "string",
"ImageUrl": "string",
"ShortDescription": "string"
}
Here is some question from me:
* should i use DATE / String to store the object?
* where should i perform this action? under my fragment / adapter?
Appreciate if any source / example provided.
<TextView
android:id="#+id/list_offers_startDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="3dp"
android:text="#{offers.StartDate}"
android:textColor="#color/colorGrayText"
android:textSize="#dimen/list_fontsize"
/>
<TextView
android:id="#+id/list_offers_endDate"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="#{offers.ExpiredDate}"
android:textColor="#color/colorGrayText"
android:textSize="#dimen/form_fontsize"
/>
* where should i perform this action? under my fragment / adapter?
perform this in onBindViewHolder of your adapter,
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position){
if (isDateExpired(listItems.get(position).getStartDate(),listItems.get(position).getEndDate())){
viewHolder.dealsExpiredtextview.setVisibility(View.GONE);
}else {
viewHolder.dealsExpiredtextview.setVisibility(View.VISIBLE);
}
}
add this method in your adapter,
public boolean isDateExpired(String startDate, String endDate) {
SimpleDateFormat dfDate = new SimpleDateFormat("dd-MM-yyyy");
boolean b = false;
try {
if (dfDate.parse(startDate).before(dfDate.parse(endDate))) {
return true; // If start date is before end date.
} else if (dfDate.parse(startDate).equals(dfDate.parse(endDate))) {
return false; // If two dates are equal.
} else {
return false; // If start date is after the end date.
}
} catch (ParseException e) {
e.printStackTrace();
return false;
}
}
should i use DATE / String to store the object?
Yes you have to save both values in Date or string.
where should i perform this action? under my fragment / adapter?
You have to perform this function in your adapter. while populate data to view.
compare date :
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date StartDate= sdf.parse(StartDate);
Date ExpiredDate= sdf.parse(ExpiredDate);
if (StartDate.after(ExpiredDate)) {
//create your logic here
}
Hope it will help you!!
You can use timestamp to do this kind of time checking thing. Send start and end timestamp in your json. And you can do this in your adapter.
Yes, I think you should use Date to represent start date and whatever other date you have, it makes more sense.
I don't think your Adapter/View is the best place do to this conversion. You should either have your parser do that for you OR you could do some post processing on your List of objects once they have been fetched from the network. Preferably even on a background thread.
Parsing those Strings to Dates in your Adapter is kind of wasteful and might make your RecyclerView a bit laggy. It will cause for repeated calculations of the same values and possibly a lengthy date parsing on the UI thread.
Firstly if you want change textview text to "DEALS EXPIRED" you should perform action under your adapter.
If you don't want parse string again you can store date as Date object.
You can parse your date like this.
Instant instant = Instant.parse( "2018-04-27T03:06:18.890Z" );
Date date = java.util.Date.from( instant );
if ( Calendar.getInstance().after( date ) ) {
// if this statement is true deal is expired.
}
Related
I am building a list in flutter and need to sort it by date by showing the most recent timestamp first.
The list is created from a json like the one below:
[
{
"id":100,
"timestamp":"2021-02-02T15:15:11Z",
"name":"Entry1"
},
{
"id":101,
"timestamp":"2021-03-02T11:12:56Z",
"name":"Entry2"
}
]
Once the json is fetched with the fetchEntries function, I'd like to sort the list. This is my code:
class Values extends Object {
int id;
String timestamp;
String name;
Values(
{this.id,
this.timestamp,
this.name});
Values.fromJson(Map<String, dynamic> json) {
id = json["id"];
timestamp = json["timestamp"];
name = json["name"];
}
}
List<Values> _myList = [];
fetchReport() {
_timer = new Timer.periodic(Duration(seconds: 1), (timer) {
fetchEntries(dates.id.toString(), dates.from, dates.to)
.then((value) => {
_myList.addAll(value),
_postsController.add(1),
setState(() {})
});
_timer.cancel();
});
//This is the sort code that doesn't work
_myList.sort((a,b)=> a.timestamp.compareTo(b.timestamp));
}
Alternatively, the list can be sorted by id in decreasing order but the timestamp method is preferred. Any suggestions how to do it properly?
It is better to parse time after fetch data.
_myList.sort((a,b) {
DateFormat formatter = DateFormat("yyyy-MM-ddTHH:mm:ssZ");
DateTime aTime = formatter.parse(a["timestamp"]);
DateTime bTime = formatter.parse(b["timestamp"]);
return aTime.compareTo(bTime);
//return bTime.compareTo(aTime);
}
I think that issue why sorting does not work is that _myList.sort function is called before _myList is filled with data. The reason of that is that _myList is populated in future (when callback of fetchEntires(...).then) is called, while sort function is called right after timer is created (after Timer.periodic constructor).
In order to fix that you need to move _myList.sort to callback just after list is populated with data.
Regarding sorting itself.. While it should work comparing date in the format of your example, I would rather parse time to milliseconds and then compare those instead. Reason is that once you change date format to different one, like 'dd-MM-yyyy' sorting will be broken.
I have a room database. I have a column for date and it's saved as string.
I used this query for sort my column :
#Query("SELECT * FROM session WHERE class_id = :classId ORDER BY session_date ASC")
List<SessionEntry> getAllSessions(int classId);
Result :
1398/11/25
1398/11/29
1398/12/5
1398/2/14
1398/4/25
1398/6/17
1398/6/30
1398/7/9
1398/9/14
but i want to sort like this :
1398/2/14
1398/4/25
1398/6/17
1398/6/30
1398/7/9
1398/9/14
1398/11/25
1398/11/29
1398/12/5
Is there any way I could order by Date as String without modifying the database structure ?
in my case it is working as I have like float type formate :
#Query("SELECT * FROM growthlogdata WHERE babyid = :childid Order By CAST(dateGrowth AS FLOAT) ASC")
List<SessionEntry> getAllSessions(int classId);
First answer, don’t store dates as strings, use a proper date datatype.
However, if I understand correctly that your SQLite database hasn’t got a date datatype, #matdev is correct: The best solution is to change the format into yyyy-mm-dd. This conforms with ISO 8601 and will sort chronologically.
I found a solution but it's not best.
This way is for when you can't change your Date Column from String to another type
List<SessionEntry> sessionEntries = mDb.sessionDao().getAllSessions(classId);
Collections.sort(sessionEntries, comparing(SessionEntry::convertStringToDate));
Session Entry :
public class SessionEntry {
.
.
.
public Date convertStringToDate() {
try {
return new SimpleDateFormat("yyyy/MM/dd").parse(getSessionDate());
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
I'm making a social media app, I am sending user's posts to firebase and then I'm retrieving them in Android listView, but I am getting the newer posts at the bottom. I want my app to work just like Facebook i.e to fetch data and set them on listView according to the precedence of time (newer posts on top).
To solve your problem, you need to add for each post in you database, a new field containing a TIMESTAMP and then order the posts accordingly to this. To set the TIMESTAMP i recomand you using ServerValue.TIMESTAMP and for getting the data back the following method:
public static String getTimeDate(long timeStamp){
try{
DateFormat dateFormat = getDateTimeInstance();
Date netDate = (new Date(timeStamp));
return dateFormat.format(netDate);
}
catch(Exception e){
return "date";
}
}
Hope it helps.
How to modify realm result data when dealing with date and time? ASCENDING and DESCENDING is not enough for me.
Say for example I am getting a task thats within an hour of due?
RealmResults<Task> tmp = realm.where(Task.class).findAll();
for (final Task task : tmp) {
String dateFormat = Utility.TIMEFORMAT;
String current = "2:30:00 PM";
Date currentTime = new Date(task.gettime());
//currentTime = new SimpleDateFormat(dateFormat).parse(current);
if( isIncomingWithInHour(currentTime, calendar)){
realmresult.add(tmp) /// this result in error.
}
}
As you can see ASCENDING and DESCENDING wont work in this kind of sorting. Anyway to give the reamlResult back to the adapter? Realmresult has an onchangeListener and I want to use that.
Instead of
RealmResults<Task> tmp = realm.where(Task.class).findAll();
You can do something like
RealmResults<Task> tasksInOneHour = realm.where(Task.class)
.greaterThanOrEqualTo("time", startTime)
.lowerThan("time", endTime)
.findAll();
Time constraints - while it is not clear in field of which type you store time in your Task class i'll provide an answer for a long field (and if it's not long, i suggest you to use it). Realm has a nice query picking capabilities, which we can make a use of:
RealmResults <Task> tasksInOneHourList =
realm.where(Task.class).between("TIME_LONG_FIELD_NAME", CURRENT_TIME, CURRENT_TIME + HOUR_IN_MILLIS).findAll();
Notify adapter - you can update adapter data as the following:
tasksInOneHourList.addChangeListener(new RealmChangeListener<RealmResults<Task>>() {
#Override
public void onChange(RealmResults<Task> tasks) {
adapter.notifyDataSetChanged();
}
});
Hello I am creating an Android app that lists local events happening around my campus. Each "event" has children for storing the title, image, category, info, and date. I was wondering what the best way would be to delete events that are past the current date. The date is formatted mm/dd/yy. I don't have much experience with using date functions in Java, and could use some advice.
Here is an example of an event. Here is the source code for reference. Any help is greatly appreciated.
The best practice is to save your data as a TIMESTAMP like this ServerValue.TIMESTAMP.
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
Map<String, Object> map = new HashMap<>();
map.put("time", ServerValue.TIMESTAMP);
ref.child("yourNode").updateChildren(map);
And to get the data back, i suggest you use this method:
public static String getTimeDate(long timeStamp){
try{
DateFormat dateFormat = getDateTimeInstance();
Date netDate = (new Date(timeStamp));
return dateFormat.format(netDate);
} catch(Exception e) {
return "date";
}
}
To solve your problem, you only need get the date from your database and compare it with the current date and time. If the value of TIMESTAMP is less than the current date and time, than you can delete that particular event.
Hope it helps.
You can filter the fire base response on date itself
ex:
DatabaseReference mDatabaseReference =FirebaseDatabase.getInstance().getReference().child("table name");
ref.orderByChild("date").startAt(startDate).endAt(endDate).on("child_added", function(snapshot){
console.log("got the data!", snapshot);
});