Finding out the closer time between two times - java

I wish to ask some question at Java. I have list of time (String) which i parsed from JSON data. I need to find which time is closer to system time. Its like this, now time is 16:40. And my time list contains
"16:32", "16:38", "16:44", "16:50" and so on. For 16:40, 16:38 is closer than 16:44 and i need to find this. I've tried to get current index and next index, parse them and initate new Calender and so on. But i cant figure out how can i do next.
Any solutions for this problem?
String returnTime = current.getDonus();
if (i < list.size() + 1) {
TimeList nextOne=list.get(i+1);
String nextReturnTime = nextOne.getDonus();
String[] parsedNextReturn = nextReturnTime.split(":");
String[] parsedReturn = returnTime.split(":");
Date date = new Date();
Calendar calNextReturn= Calendar.getInstance();
calNextReturn.setTime(date);
calNextReturn.set(Calendar.HOUR_OF_DAY, Integer.parseInt(parsedNextReturn[0]));
calNextReturn.set(Calendar.MINUTE, Integer.parseInt(parsedNextReturn[1]));
calNextReturn.set(Calendar.SECOND, 0);
calNextReturn.set(Calendar.MILLISECOND, 0);
Calendar calCurrentReturn= Calendar.getInstance();
calCurrentReturn.setTime(date);
calCurrentReturn.set(Calendar.HOUR_OF_DAY, Integer.parseInt(parsedReturn[0]));
calCurrentReturn.set(Calendar.MINUTE, Integer.parseInt(parsedReturn[1]));
calCurrentReturn.set(Calendar.SECOND, 0);
calCurrentReturn.set(Calendar.MILLISECOND, 0);
Calendar calSystem = Calendar.getInstance();
calSystem.setTime(date);
calSystem.set(Calendar.SECOND, 0);
calSystem.set(Calendar.MILLISECOND, 0);
}

Try this:
long smallestABS = Long.MAX_VALUE;
long systemTime = System.currentTimeMillis();
long timeClosest;
for (long time : timeList) {
long abs = Math.abs(systemTime - time);
if(smallestABS > abs){
smallestABS = abs;
timeClosest = time;
}
}

Related

date range search with respect to number of chunk size

I wanted to do a date range search in java suppose I wanted to search from 10-22-2019 to the present date.
But the question is to do the date range search in the chunk size of two weeks(consider this can vary but in form weeks) for eg here start date will 10-22-2019 but the end date will start date + 2 weeks added to it after the date range search is done for this and taking the result. Now the new start date should be were the previous date range search ended. and the end date should be now 2 weeks from the new start date again the search and this keeps on until I get till the present date.
public static IEnumerable<Tuple<DateTime, DateTime>> SplitDateRange(DateTime start, DateTime end, int dayChunkSize)
{
DateTime chunkEnd;
while ((chunkEnd = start.AddDays(dayChunkSize)) < end)
{
yield return Tuple.Create(start, chunkEnd);
start = chunkEnd;
}
yield return Tuple.Create(start, end);
}
Got this from one of the answers but have trouble in implementing in my situtation.
Simple iterative solution :
LocalDate start = LocalDate.parse("2019-10-22");
LocalDate end = LocalDate.now();
LocalDate chunckStart = start;
while (chunckStart.plusDays(15).isBefore(end)) {
doTheThing(chunckStart, chunckStart.plusDays(15));
chunckStart = chunckStart.plusDays(16);
}
doTheThing(chunckStart, end);
You can try it here.
try:
public static Iterator<Pair<LocalDate, LocalDate>> splitDataRange(LocalDate start, LocalDate end, int dayChunkSize) {
return new Iterator<Pair<LocalDate, LocalDate>>() {
private LocalDate chunkStart = start;
private LocalDate chunkEnd = start.plusDays(dayChunkSize);
#Override
public boolean hasNext() {
return end.compareTo(chunkEnd) > 0;
}
#Override
public Pair<LocalDate, LocalDate> next() {
Pair<LocalDate, LocalDate> chunk = new Pair<>(chunkStart, chunkEnd);
chunkStart = chunkEnd;
chunkEnd = chunkEnd.plusDays(dayChunkSize);
return chunk;
}
};
}
public static void main(String[] args) {
Iterator<Pair<LocalDate, LocalDate>> periodIterator = splitDataRange(LocalDate.of(2019, 3, 1),
LocalDate.of(2019, 5, 1), 20);
while (periodIterator.hasNext()) {
Pair<LocalDate, LocalDate> startEnd = periodIterator.next();
System.out.println(String.format("from %s to %s"
, startEnd.getValue0(), startEnd.getValue1()));
}
}
The Pair api is from:
<dependency>
<groupId>org.javatuples</groupId>
<artifactId>javatuples</artifactId>
<version>1.2</version>
</dependency>
Here's a solution using Streams and LocalDate:
LocalDate start = LocalDate.of(2020, 2, 28);
LocalDate end = LocalDate.now();
int step = 7;
start
.datesUntil(end, Period.ofDays(step))
.map(date -> {
LocalDate proposedEnd = date.plusDays(step);
LocalDate chunkEnd = proposedEnd.compareTo(end) > 0 ? end : proposedEnd;
return new SimpleEntry<>(date, chunkEnd);
})
.forEach(chunk -> System.out.println(chunk.getKey() + " until " + chunk.getValue()));
It generates the same output as the corresponding C# program.
The datesUntil method requires Java 9. Otherwise, if you're using Java 8, then you could use a helper method instead:
public static Stream<LocalDate> datesUntil(LocalDate from, LocalDate toExclusive) {
long daysBetween = ChronoUnit.DAYS.between(from, toExclusive);
return Stream.iterate(from, t -> t.plusDays(1))
.limit(daysBetween);
}

How to validate range in android?

I'm new to Android programming and I'm currently developing an app. Can someone help me on how to validate the date that is being input by the user if is it in range 7 days?
so, i have two string 'startDay' and 'endDay' where user input
startDay = 1/2/2017
endDay = 6/2/2017
then it went on the next step. and if user input
startDay = 1/2/2017
endDay = 9/2/2017 then it return message 'maximum 7 days'
there is the code that i made
#Override
public void onClick(View v) {
if (v==btnSearch){
String startDaystr = startDay.getText().toString();
String startMonthtstr = startMonth.getText().toString();
String endDaystr = endDay.getText().toString();
String endMonthstr = endMonth.getText().toString();
String endYearstr = endYear.getText().toString();
if(Integer.valueOf(startDaystr) >1 && Integer.valueOf(endDaystr) < 8){
sharedPreferenceCustom = SharedPreferenceCustom.getInstance(getContext());
sharedPreferenceCustom.putSharedPref("startDay", startDaystr);
sharedPreferenceCustom.putSharedPref("startMonth",startMonthtstr);
sharedPreferenceCustom.putSharedPref("endDay",endDaystr);
sharedPreferenceCustom.putSharedPref("endMonth",endMonthstr);
sharedPreferenceCustom.putSharedPref("endYear",endYearstr);
startActivity(new Intent(getActivity(), activity_history.class));
}else{
Toast.makeText(getActivity(), "Maximum 7 days!", Toast.LENGTH_LONG).show();
}
}
}
but when im input
startDay = 22/2/2017
endDay = 25/2/2017
the result is 'maximum 7 days' it should be return to the next step
please help me..im searched and tried also but not get such a solution..
I added startYearStr, please note that.
Use below code :
String startDaystr = startDay.getText().toString();
String startMonthtstr = startMonth.getText().toString();
String startYearstr = startYear.getText().toString();
String endDaystr = endDay.getText().toString();
String endMonthstr = endMonth.getText().toString();
String endYearstr = endYear.getText().toString();
Calendar startDate = Calendar.getInstance();
startDate.set(Calendar.DAY_OF_MONTH, Integer.parseInt(startDaystr));
startDate.set(Calendar.MONTH, Integer.parseInt(startMonthtstr));
startDate.set(Calendar.YEAR, Integer.parseInt(startYearstr));
startDate.set(Calendar.HOUR_OF_DAY, 0);
startDate.set(Calendar.MINUTE, 0);
startDate.set(Calendar.SECOND, 0);
Calendar endDate = Calendar.getInstance();
endDate.set(Calendar.DAY_OF_MONTH, Integer.parseInt(endDaystr));
endDate.set(Calendar.MONTH, Integer.parseInt(endMonthstr));
endDate.set(Calendar.YEAR, Integer.parseInt(endYearstr));
endDate.set(Calendar.HOUR_OF_DAY, 0);
endDate.set(Calendar.MINUTE, 0);
endDate.set(Calendar.SECOND, 0);
long diff = endDate.getTimeInMillis() - startDate.getTimeInMillis();
long dayCount = diff / (24 * 60 * 60 * 1000);
dayCount gives you the day difference between two dates.
To compare dates you would want to use the Java Date or Calendar objects but reading in the initial dates from an EditText like you are doing wouldn't be safe. If you aren't validating the input, a user could enter in something like "February 2nd 2016" when you are expecting "2/2/2016" so you might want to change it from a freeform EditText to a date picker so you can control how the user inputs the dates first.
Once you have the two dates in a supported Java object you can compare them against each other. This answer has an example how to do the comparison.

How to count the number of events on a specific calendar for today only?

I'm trying to build a simple example application that counts the number of events on a specific calendar (I know the CALENDAR_DISPLAY_NAME of the Calendar) for today only.
I believe I need to query todays events with CalendarContract, and then count the number of rows in the cursor?
Is that correct? What would be the minimal, most efficient way to do the query on the single calendar, and have it return only the minimal possible set of data (event id only?) ?
This is the solution I arrived at:
First find the Calendar ID from the known name.
Then:
private Cursor getEventInstancesCursor() { // Query for a list of GQueues Calendar instances today
// Set Calendar variable for start and end of today.
Calendar startOfDay = Calendar.getInstance();
int thisYear = startOfDay.get(Calendar.YEAR);
int thisMonth = startOfDay.get(Calendar.MONTH);
int thisDay = startOfDay.get(Calendar.DAY_OF_MONTH);
startOfDay.set(thisYear, thisMonth, thisDay, 0, 0, 0);
long startMillis = startOfDay.getTimeInMillis();
Calendar endOfDay = Calendar.getInstance();
endOfDay.set(thisYear, thisMonth, thisDay, 23, 59, 59);
long endMillis = endOfDay.getTimeInMillis();
long GQueuesCalID = getGQueuesCalID();
Cursor eventsCursor = null;
ContentResolver eventsCR = getContentResolver();
String selection = CalendarContract.Instances.CALENDAR_ID + " = ?";
String calIDString = String.valueOf(GQueuesCalID);
String[] selectionArgs = {calIDString};
try {
return eventsCursor = eventsCR.query(
CalendarContract.Instances.CONTENT_URI.buildUpon()
.appendPath(Long.toString(startMillis))
.appendPath(Long.toString(endMillis))
.build(),
InstancesQuery.PROJECTION,
selection,
selectionArgs,
null);
} catch (Exception e) {
Log.e(TAG, "Error querying calendar API", e);
return null;
}
}
Then just count the cursor rows.

netbeans: how to set value to control which is retrieved from database?

I want to fetch records from database & want to set on form. In this form I am using JDateChooser from JCalendar. I have written the following code for this:
public void showdata()
int a=leaveView.getSelectedRow();
int b=(Integer)leaveView.getValueAt(a, 0);
String c=(String)leaveView.getValueAt(a, 1);
String d=(String)leaveView.getValueAt(a, 2);
String e=(String)leaveView.getValueAt(a, 3);
String f=(String)leaveView.getValueAt(a, 4);
String g=(String)leaveView.getValueAt(a, 5);
String h=(String)leaveView.getValueAt(a, 6);
int i=(Integer)leaveView.getValueAt(a, 7);
String j = (String)leaveView.getValueAt(a, 8);
String k = (String)leaveView.getValueAt(a, 9);
AL.empid.setSelectedItem(b);
AL.empname.setText(c);
AL.empname.setEditable(true);
AL.department.setText(d);
AL.department.setEditable(true);
AL.leavetype.setSelectedItem(e);
AL.other.setText(f);
AL.other.setEditable(true);
AL.jDateChooser1.setDate(g);
AL.jDateChooser2.setDate(h);
AL.noofdays.setText(""+i);
AL.noofdays.setEditable(true);
AL.singleday.setSelected(true);
AL.multipleday.setSelected(true);
}
but it's setting today's date to JDateChooser by default... it's not displaying the date which is retrieved from database... The above code is throwing an error at lines AL.jDateChooser1.setDate(g) and AL.jDateChooser2.setDate(h) for g & h...What can I do?
Assuming you are using this JCalendar API
From the javadocs setDate accepts a date object and not a string. First convert(parse) the dateString(g & h) to Date objects then set the date.
DateFormat df = new SimpleDateFormat("dd/MM/yyyy"); //adjust this according to your requirement
Date gDate,hDate;
        try {
            gDate = df.parse(g);
hDate = df.parse(h);
        } catch (ParseException e) {
            e.printStackTrace();
        }
AL.jDateChooser1.setDate(gDate);
AL.jDateChooser2.setDate(hDate);
for some example date formats,visit http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html

Java String Parsing and Evaluating

All,
I am in the process or rewriting some code that I wrote a while back. The objective of the code was to calcualte a date and time based on a string in the following formats:
DayStart+2Hour+1Day-2Minutes
NOW+20Day
MonthStart+1Month
Which would take the start of the day (in local time), e.g. 2011-09-15 00:00:00 BST (2011-09-15 23:00 GMT) then add 2 hours, add 1 day, and subtract 2 minutes.
The implementation is in Java and the original algorithm was pretty basic. It iterated through each character in the string and appended to a buffer. The buffer was then checked to see if it ended with the strings I was looking (date specifier e.g MINUTE, HOUR, DAYSTART, etc.) for then extracted the number and added to an ArrayList where DateOffset was a simple class with a int and String which was date specifier. Here is some sample code:
// hard coded for sample
String s = "DayStart+2Hour+1Day-2Minutes";
StringBuilder sbBuffer = new StringBuilder();
String buffer;
// iterate through date string
for (char c : s.toCharArray()) {
sbBuffer.append(c);
buffer = sbBuffer.toString();
// check to see the end of the buffer string is what we expect
if (buffer.endsWith("DAYSTART")) {
offsets.add(new DateOffset(0, "DAYSTART"));
sbBuffer = new StringBuilder();
} else if (buffer.endsWith("DAY") && buffer.length() > 3) {
String numberStringPart = buffer.substring(0, buffer.length() - 3);
numberStringPart = numberStringPart.replaceAll("[+]", "").trim(); // need as parseInt does not like the +.
offsets.add(new DateOffset(Integer.parseInt(numberStringPart), "DAY"));
sbBuffer = new StringBuilder();
} ... and so on ...
else {
}
}
After the string was parsed I iterated through ArrayList to calculate my datetime.
The problem with the above is probably not efficient although we have experienced no problems. It also does not pick up any errors so you could enter DayStart+2GKGKER.
I'm just trying to come up with some fresh and neat ideas on what to use to rewrite it. I have done a little regex but not too sure if this would be the best route.
Any thoughts?
Thanks,
Andez
Define a grammar for your expressions. Take a look at the ANTLR framework to help you construct a grammar and process your expressions.
Woohoo, that was fun! Thank you! :-)
public class DateExpressions {
private Map<String, Date> dateVariables;
private Map<String, Integer> temporalUnits;
private Map<Character, Integer> temporalOperations;
public static DateExpressions createInstance() {
DateExpressions de = new DateExpressions();
Calendar c = Calendar.getInstance();
de.setVariable("NOW", c.getTime());
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
de.setVariable("DayStart", c.getTime());
c.set(Calendar.DAY_OF_MONTH, 1);
de.setVariable("MonthStart", c.getTime());
return de;
}
public DateExpressions() {
this.dateVariables = new HashMap<String, Date>();
this.temporalUnits = new HashMap<String, Integer>();
this.temporalUnits.put("Second", Calendar.SECOND);
this.temporalUnits.put("Minute", Calendar.MINUTE);
this.temporalUnits.put("Hour", Calendar.HOUR_OF_DAY);
this.temporalUnits.put("Day", Calendar.DATE);
this.temporalUnits.put("Month", Calendar.MONTH);
this.temporalUnits.put("Year", Calendar.YEAR);
this.temporalOperations = new HashMap<Character, Integer>();
this.temporalOperations.put('+', 1);
this.temporalOperations.put('-', -1);
}
public void setVariable(String key, Date value) {
this.dateVariables.put(key, value);
}
public Date parseExpression(String expr) throws IOException {
StringReader sr = new StringReader(expr);
String s;
int n;
char c;
int offset;
int unit;
int op = 1;
Calendar base = null;
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
while ((n = sr.read()) != -1) {
c = (char) n;
if (base == null && temporalOperations.containsKey(c)) {
s = sb2.toString();
if (!dateVariables.containsKey(s)) {
throw new IOException("Unknown variable '" + s + "' used");
}
base = Calendar.getInstance();
base.setTime(dateVariables.get(sb2.toString()));
op = temporalOperations.get(c);
sb1.setLength(0);
sb2.setLength(0);
} else if (temporalOperations.containsKey(c)) {
if (!temporalUnits.containsKey(sb2.toString())) {
throw new IOException(
"Parse error: unknown temporal unit used '"
+ sb2.toString() + "'");
}
offset = Integer.parseInt(sb1.toString());
unit = temporalUnits.get(sb2.toString());
base.add(unit, op * offset);
op = temporalOperations.get(c);
sb1.setLength(0);
sb2.setLength(0);
} else if (Character.isDigit(c)) {
sb1.append(c);
} else {
sb2.append(c);
}
}
if (!temporalUnits.containsKey(sb2.toString())) {
throw new IOException("Parse error: unknown temporal unit used '"
+ sb2.toString() + "'");
}
offset = Integer.parseInt(sb1.toString());
unit = temporalUnits.get(sb2.toString());
base.add(unit, op * offset);
return base.getTime();
}
public static void main(String[] args) throws IOException {
DateExpressions de = DateExpressions.createInstance();
System.out.println(de.parseExpression("DayStart+2Hour+1Day-2Minute"));
System.out.println(de.parseExpression("NOW+20Day"));
System.out.println(de.parseExpression("MonthStart+1Month"));
}
}
If you're after rapid experimentation, sometimes a literate API combined with on the fly compilation is an easy way to go.
So, your example could look like (given appropriate static imports)
daystart().plus()
.hours(2).plus()
.days(1).minutes(2)
or even (given milliseconds as the basic units)
daystart() + hours(2) + days(1) - minutes(2)
Regex seems to be the best bet for such a scenario. Although, I'm puzzled why would you want to interpret strings in this manner, rather than having sophisticated APIs.

Categories