how to sort date in cloudant query - android

i want to sort my data as par desc date in local cloudant query.
i have insert_ts in my database document.
my code for simple query is:-
public List<BasicDocumentMAP> allTasksWithAllArg(Map<String, Object> query, int skip, int limit, List<String> fields, List<Map<String, String>> sortDocument) {
int nDocs = this.sunDatastore.getDocumentCount();
QueryResult all = this.im.find(query, skip, limit, fields, sortDocument);
List<BasicDocumentMAP> arrayListBasicDocumentMAP = new ArrayList<>();
// Filter all documents down to those of type Task.
for (DocumentRevision rev : all) {
}}
please help me to sort data as date wise. thank you

Try this code:
Sql query :
Select _id , _rev , insert_ts , title from table
where year=2010 order by insert_ts
Cloudant query :
{
"selector": {
"year": {
"$gt": 2010
}
},
"fields": ["_id", "_rev", "insert_ts", "title"], //
"sort": [{"insert_ts": "asc"}]
}

Update: The original answer (at the bottom) shows you how to sort by year (OP asked how to get the year, so I assumed that was how they wanted to sort). This is how to sort by date:
Either change the insert_ts field to be a date, or add a new field that is a date, for example:
Date insertTsDate = null;
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy-hh-mm-ss-SS");
try {
insertTsDate = dateFormat.parse(insert_ts);
}
catch (Exception e) {
// handle exception
}
Then add a new field to your document called insert_ts_date (or whatever you want to call it), set it to the insertTsDate variable above, and sort like so:
List<Map<String, String>> sortDocument = new ArrayList<Map<String, String>>();
Map<String, String> sortByInsertTsDate = new HashMap<String, String>();
sortByInsertTsDate.put("insert_ts_date", "asc");
sortDocument.add(sortByInsertTsDate);
Original Answer:
I think you are going to have to explicitly add a year property to your document. If you have the year then just add it to your document. If you need to parse it from the string you can use regex or the Date/Calendar classes to parse the date:
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy-hh-mm-ss-SS");
try {
Date date = dateFormat.parse(insert_ts);
Calendar c = Calendar.getInstance();
c.setTime(date);
int year = c.get(Calendar.YEAR);
}
catch (Exception e) {
// handle exception
}
Then issue your query as follows:
List<Map<String, String>> sortDocument = new ArrayList<Map<String, String>>();
Map<String, String> sortByYear = new HashMap<String, String>();
sortByYear.put("year", "asc");
sortDocument.add(sortByYear);

Related

How to serialize a json firestore Timestamp to Date?

I store a Date in Firestore. I get an HashMap<String, Object> from firestore and i want to recreate my object from it.
Before implementing the Date the working code was :
HashMap<String, Object> document = new HashMap<String, Object>();
document.put("name", "name");
JSONElement jsonElement = gson.toJsonTree(document);
Event event = gson.fromJson(jsonElement , Event.class);
I have now add the field
#ServerTimestamp
private Date dateOfEvent;
But when i try to serialize it i get the following error:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected STRING but was BEGIN_OBJECT at path $.dateOfEvent
Because the JsonElement "dateOfEvent" look like this because it's a Firestore Timestamp:
{"dateOfEvent": {"nanoseconds":0,"seconds":1584921600}, "name": "test Event"}
Thanks for your time and your help.
Gson is expecting a Date string like 2020-02-27T09:00:00 but it's actually an object. You could setup your classes like this and add a helper method to get dateOfEvent as a Date:
class Event {
private String name;
private MyDate date;
}
class MyDate {
private Long nanoseconds;
private Long seconds;
// getters/setters for nanoseconds, seconds...
public Date asDate() {
// convert to date
}
}

Hashmap with Arraylist as values Android

I am developing an android application and I am using a Hashmap to store some data the app works fine when I define the Arraylist this way
ArrayList<String> eventList = new ArrayList<>();
but the app crashes when I change it to:
ArrayList<String> eventList = hmap.get(date);
I need to know the reason why?.
And here is the whole function in case you need to have a look
HashMap<Date, ArrayList<String>> hmap = new HashMap<>();
void eventMaker(String d, String ev) {
Date date = null;
try {
date = df.parse(d);
} catch (ParseException e) {
e.printStackTrace();
}
long epoch = date.getTime();
Event event = new Event(Color.RED,epoch,ev);
compactCalendar.addEvent(event);
ArrayList<String> eventList = new ArrayList<>();
eventList.add(ev);
hmap.put(date,eventList);
}
You need to cast the value of Hashmap to required type .
ArrayList<String> eventList =(ArrayList<String>) hmap.get(date);
The problem was that I was trying to get a value of a key that does not exist, I solved it like this:
if(!hmap.containsKey(date)){
ArrayList<String> eventList =new ArrayList<>();
eventList.add(ev);
hmap.put(date,eventList);
}
else{
ArrayList<String> eventList = hmap.get(date);
eventList.add(ev);
hmap.put(date,eventList);
}

NumberFormatException Invalid Long with Calendar

I am having problems with this NumberFormatException Invalid Long. The log cat is showing that the error is coming from the Long.parseLong part of the method.
public static String getDateTimeStr(String p_time_in_millis) {
SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
Date l_time = new Date(Long.parseLong(p_time_in_millis));
return sdf.format(l_time);
}
Can someone tell me why this code works fine when I fetch and display the data in certain calendars then in other calendars on my device I get this NumberFormatException Invalid Long please?
Edit: Here is the rest of the code…
private void getEvents() {
Uri l_eventUri;
ArrayList<Map<String, String>> allStudents = new ArrayList<Map<String, String>>();
if (Build.VERSION.SDK_INT >= 8) {
l_eventUri = Uri.parse("content://com.android.calendar/events");
} else {
l_eventUri = Uri.parse("content://calendar/events");
}
String[] l_projection = new String[]{"title", "dtstart", "dtend"};
#SuppressWarnings("deprecation")
Cursor l_managedCursor = this.managedQuery(l_eventUri, l_projection, "calendar_id=" + m_selectedCalendarId, null, "dtstart DESC, dtend DESC");
if (l_managedCursor.moveToFirst()) {
int l_colTitle = l_managedCursor.getColumnIndex(l_projection[0]);
int l_colBegin = l_managedCursor.getColumnIndex(l_projection[1]);
int l_colEnd = l_managedCursor.getColumnIndex(l_projection[2]);
String l_title = String.valueOf(l_colTitle);
String l_begin = Integer.toString(l_colBegin);
String l_end = Integer.toString(l_colEnd);
do {
Map<String, String> map = new HashMap<String, String>();
l_title = l_managedCursor.getString(l_colTitle);
l_begin = getDateTimeStr(l_managedCursor.getString(l_colBegin));
l_end = getDateTimeStr(l_managedCursor.getString(l_colEnd));
map.put("eventTitles", l_title);
map.put("event_begin", l_begin);
map.put("event_end", l_end);
allStudents.add(map);
} while (l_managedCursor.moveToNext());
l_managedCursor.close();
SimpleAdapter adapter = new SimpleAdapter(this, allStudents, R.layout.notice_layout, new String[] { "eventTitles", "event_begin", "event_end" }, new int[] { R.id.tvTitle, R.id.tvBody, R.id.tvTeacherCode});
listViewCalendar.setAdapter(adapter);
}
}
Edit 2:
For some reason the code works fine without this line of code so I've nailed it down to this line of code.
l_end = getDateTimeStr(l_managedCursor.getString(l_colEnd));
Why does the l_colEnd get caught up in an NumberFormatExcetion? When the following line of code could be also caught up in the same NumberFormatException because it is enquiring about the same int format?
l_begin = getDateTimeStr(l_managedCursor.getString(l_colBegin));
Thank you too all who have helped. The other interesting thing also is when I add this
int l_cnt = 0;
do {
++l_cnt;
} while (l_managedCursor.moveToNext() && l_cnt < 100);
to the while clause as shown below at the end of the following code the app works fine with no lines of code throwing a NumberFormatException..
if (l_managedCursor.moveToFirst()) {
int l_cnt = 0;
int l_colTitle = l_managedCursor.getColumnIndex(l_projection[0]);
int l_colBegin = l_managedCursor.getColumnIndex(l_projection[1]);
int l_colEnd = l_managedCursor.getColumnIndex(l_projection[2]);
String l_title = String.valueOf(l_colTitle);
String l_begin = Integer.toString(l_colBegin);
String l_end = Integer.toString(l_colEnd);
do {
Map<String, String> map = new HashMap<String, String>();
l_title = l_managedCursor.getString(l_colTitle);
l_begin = getDateTimeStr(l_managedCursor.getString(l_colBegin));
l_end = getDateTimeStr(l_managedCursor.getString(l_colEnd));
map.put("eventTitles", l_title);
map.put("event_begin", l_begin);
map.put("event_end", l_end);
allStudents.add(map);
++l_cnt;
} while (l_managedCursor.moveToNext() && l_cnt < 100);
Can someone tell me why this code works fine when I fetch and display
the data in certain calendars then in other calendars on my device I
get this NumberFormatException Invalid Long please?
Date l_time = new Date(Long.parseLong(p_time_in_millis));
IMO. This code is "bad" code.
Why? You try to fetch unknown data from unchecked sources
"content://com.android.calendar/events" and "content://calendar/events"
Almost everybody can access calendars and save whatever he like... Sadly there is no rule there for using this! So making a wild guess an app is using this event column to save data in another that your expected format.
Regarding the check l_cnt < 100, where fail stops
It's not failing because the error happens to 101 event or later!
My solution would to check my data, and never trust that other apps will act as I expected or as they should.
So I suggest to change getDateTimeStr method as follows:
public static String getDateTimeStr(String p_time_in_millis) {
SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
long timestamp = 0;
try {
timestamp = Long.parseLong(p_time_in_millis)
} catch(NumberFormatException e) {
Log.w("getDateTimeStr", "Cannot convert '"+p_time_in_millis+"' to long");
e.printStackTrace(); // Prints full error exception
}
Date l_time = new Date(timestamp);
return sdf.format(l_time);
}
Remove the l_cnt < 100 check and leave the code to run checking your logcat! You will now have a better overview of what is happening and also your bad data dates will be 1/1/1970 (due to 0 timestamp) code can be changed responsively in order to handle that dates which does not have the expected format.
Some ideas for handling errors:
Make getDateTimeStr throw an exception to the getEvents() which could catch it and ignore the event with the unexpected data. (Handling logic, ignoring what I cannot understand.)
Recognize the format of the p_time_in_millis in each different case and use different DATE_TIME_FORMAT types regarding the exact format of each event. Okey, that's needs a lot of investigation and still can fail. Also you have to add the case that the format is still unknown so maybe ignore it or use a default value in order not to crash.
Generally, you always try to write a stable app that will not fail if another app saves data in a different format (because it like so or due to its own bug)

How to fetch data's between two dates in android (not sqlite)?

I tried to do to fetch the data's between from and to dates.
I did it on sql lite,it works and
I tried in android coding part,it doesn't work,could you guys please help
protected void adddata1() throws ParseException {
Database db=new Database(Reportmonth.this);
SQLiteDatabase sb=db.getReadableDatabase();
String a=from.getText().toString();
String b=to.getText().toString();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date a1=sdf.parse(a);//convert string to date
Date b1=sdf.parse(b);//convert string to date
Cursor cus=sb.rawQuery("select * from expenz where daty between '" + a1 +"' AND '"+b1+"'",null);
cus.moveToFirst();
for(int i=0;i<cus.getCount();i++)
{
if(cus!=null) //i think the error starts from this onwards.
{
soi.setText(cus.getString(0));
Log.i("",cus.getString(0));
desc.setText(cus.getString(3));
dat.setText(cus.getString(1));
woc.setText(cus.getString(2));
amount.setText(cus.getString(5));
adddata();
search.setClickable(false);
}
cus.moveToNext();
}
}
It is not advisable to store date in database as varchar as when it comes to situation like yours, its a real pain
Still below I have shown a work around, where you can extract all data from the table, convert the date column in the table from string to Date object and then do your comparison. But this will hit the performance a lot specially when the rows in your database is really high.
//For storing the rows that are in between the date range
ArrayList<HashMap<String, String>> rowList = new ArrayList<HashMap<String, String>>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//Important that the date should be in the same format as specified above
Date startDate = sdf.parse(a);//convert string to date
Date endDate = sdf.parse(b);//convert string to date
Cursor cus = sb.rawQuery("select * from expenz",null);
if (cursor.moveToFirst()) {
do {
try {
//Converting the database `varchar date` to `Date` object here
//Here cursor.getString(X) should be the column number of your daty column
//And also the date format in the database should also be same as "yyyy-MM-dd"
Date thisDate = sdf.parse(cursor.getString(X));
// Check if the database date is within the range
if (thisDate.after(startDate) && thisDate.before(endDate)) {
HashMap<String, String> map = new HashMap<String, String>();
//Here have the number of columns you want to have according to your database
map.put("column0", cursor.getString(0));
map.put("column1", cursor.getString(1));
map.put("column2", cursor.getString(2));
map.put("column3", cursor.getString(3));
map.put("column4", cursor.getString(4));
map.put("column5", cursor.getString(5));
rowList.add(map);
}
} catch (ParseException e) {
e.printStackTrace();
}
} while (cursor.moveToNext());
}
// Now here the rowList will have the rows between the specified date range
You could modify the inner most if loop to meet your requirements.
I hope it helps!

How to get Time range in array using android

I have an array which having time ranges like below,
String[] str ={"6.30 AM","6.10 AM","10.00 PM","7.00 PM"};
i want to get the minimum time and maximum time in above array such as "6.10 AM" and "10.00 PM".i can find out using sorting but it takes long time.Is any other method avail.Guide me,Below i sorted like,
String[] str ={"1:0 PM","2:0 AM","3:0 PM",.....};
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm aa", Locale.getDefault());
Date TimeToCompare = null,Time1 = null;
for(int i=0;i<10;i++)
{
TimeToCompare=sdf.parse(str[i]);
for(int j=i+1;j<10;j++)
{
Time1=sdf.parse(str[j]);
if(TimeToCompare.after(Time1))
{
//sorting
}
}
}
This solution makes one pass through the array, keeping track of the min and max times. Runs in O(n).
double maxTime = 0.0;
double minTime = 0.0;
for(String s : str) {
String[] parts = str.split(" ");
double time = Double.parse(parts[0]);
if (parts[1].equals("PM")) {
time += 12;
}
if (time > maxTime) {
maxTime = time;
}
if (time < minTime) {
minTime = time;
}
}
// convert doubles back into strings and print
Date-Time Values
When working with date-time values, it's usually best to work with them as date-time values.
Parse the strings as date-time values, collect them, sort the collection, and retrieve the first and last elements in collection to get earliest & latest values. Convert back to strings if needed.
Joda-Time & java.time
You can easily parse the strings to create date-time objects.
However avoid using the bundled java.util.Date & .Calendar classes in Java as they are notoriously troublesome. Furthermore, they always combine date and time-of-day while in your case you have only a time-of-day.
Use either Joda-Time or the new java.time package in Java 8. Both offer a day-of-time only class, LocalTime.
Example Code
Example code using Joda-Time 2.3.
Convert your array to Collection as I prefer to not work with arrays.
String[] strings = { "6.30 AM", "6.10 AM", "10.00 PM", "7.00 PM" };
List<String> stringList = Arrays.asList( strings );
Create an empty collection to collect our LocalTime objects as we instantiate them.
List<LocalTime> localTimes = new ArrayList<>();
Create a formatter to parse your particular string format. By the way, if you can change the source of these strings, I suggest creating strings in 24-hour format without the "AM/PM", akin to the standard ISO 8601 format.
DateTimeFormatter formatter = DateTimeFormat.forPattern( "h'.'mm aa" );
Loop through our collection of strings, parsing each one. Store the new LocalTime instance in a collection.
for ( String string : stringList ) {
LocalTime localTime = formatter.parseLocalTime( string );
localTimes.add( localTime );
}
Sort the collection of LocalTime objects, to determine the earliest and latest.
Collections.sort( localTimes ); // Ascending order. Earliest first, latest last.
Retrieve the earliest and latest.
LocalTime earliest = localTimes.get( 0 );
LocalTime latest = localTimes.get( localTimes.size() - 1 );
Dump to console.
System.out.println( "localTimes: " + localTimes );
if ( !( localTimes.isEmpty() ) ) {
System.out.println( "earliest: " + formatter.print( earliest ) );
System.out.println( "latest: " + formatter.print( latest ) );
}
When run…
localTimes: [06:10:00.000, 06:30:00.000, 19:00:00.000, 22:00:00.000]
earliest: 6.10 AM
latest: 10.00 PM
Here's a sample solution picked from ggreiner #
How to sort a list of time strings in Java or Groovy
String[] str ={"6.30 AM","6.10 AM","10.00 PM","7.00 PM"};
List<String> times = Arrays.asList(str); // convert int to list
Collections.sort(times, new MyComparator()); // use a custom comparator
Log.i("Min time is ",""+times.get(0));
Log.i("Max Time is ",""+times.get(times.size()-1));
Custom Comparator
class MyComparator implements Comparator<String>
{
private DateFormat primaryFormat = new SimpleDateFormat("h.mm a");
#Override
public int compare(String time1, String time2){
return timeInMillis(time1) - timeInMillis(time2);
}
public int timeInMillis(String time){
return timeInMillis(time, primaryFormat);
}
// in milliseconds
private int timeInMillis(String time, DateFormat format) {
Date date = null ;
try {
date = format.parse(time); //
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return (int)date.getTime();
}
}
// Try this way,hope this will help you to solve your problem.
String[] str =new String[]{"6.30 AM","6.10 AM","10.00 PM","7.00 PM"};
ArrayList<Double> list = new ArrayList<Double>();
HashMap<Double,String> map = new HashMap<Double, String>();
for (int i=0;i<str.length;i++){
list.add(Double.parseDouble(str[i].split(" ")[0]));
map.put(Double.parseDouble(str[i].split(" ")[0]),str[i]);
}
System.out.println("Min >> " +map.get(Collections.min(list)));
System.out.println("Max >> "+map.get(Collections.max(list)));
Can you use these, But you may need some pre-arragments
Collections.max(arrayList);
Collections.min(arrayList);
Depending on how you're originally filling the array of values, like are you getting the long from the system then you could compare those. Or create an class that holds the value part and the AM or PM seperately like a flag or something, so then sort between AM and PM then values. I dabbled a lot with java date and calendars, and just use JodaTime. It's convenient!

Categories

Resources