Check if a LocalDateTime is between work hours - android

I wonder what's the more efficient way to compare values to check if the current date is in a range of values.
I'd like to trigger a local notification only from Monday to Friday and from 8:00 to 18:00 (8a.m. - 6p.m.)
First I was writing this :
val current = LocalDateTime.now()
val day = current.dayOfWeek.value
val hour = current.hour
if(day != 6 && day != 7 && hour > 7 && hour < 18)
{...}
But Android Studio suggested
hour in 8..17
So should I use day != 6 && day != 7 && hour > 7 && hour < 18
Or day != 6 && day != 7 && hour in 8..17,
Or day in 1..5 && hour in 8..17,
Or something else?
What do you think?

Of the many ways you do this, you won't observe any as being "more efficient" (unless you are doing millions of evaluations).
I agree with #Tenfour04 that a much bigger consideration is readability - so that you/others can reason that the code is correct. Consider also using named constants for the days of the week (DayOfWeek.MONDAY) you can still use these in ranges. How about this then:
val current = LocalDateTime.now()
val isInWorkingHours = current.hour in 8..17
val isWorkingDay = current.dayOfWeek in DayOfWeek.MONDAY..DayOfWeek.FRIDAY
if(isInWorkingHours && isWorkingDay) {
//
}
And with an IDE like IntelliJ you get hints so that .. range syntax is easily to understand you get:

Related

How to show progress based on days interval dynamically

I have to display progress bar based on day interval suppose that i have given start days and end days so we have to show progress in progress bar in such manner so that if you will 1-3 days then there should fill same progress 3 to 6 we should fill same progress ...and like this .
Given start date and end date based on that I have followed below steps
1 . find total number of days then
2 find days difference between todays date and start date
3 tried to get degree diff between today days and no of days left based one that I set mProgress.setProgress(degrees);.
private void displayProgressView() {
Resources res = getResources();
Drawable drawable = res.getDrawable(R.drawable.circular);
final ProgressBar mProgress = (ProgressBar) findViewById(R.id.circularProgressbar);
mProgress.setProgress(0); // Main Progress
mProgress.setSecondaryProgress(360); // Secondary Progress
mProgress.setMax(360); // Maximum Progress
mProgress.setProgressDrawable(drawable);
int noOfDaysLeft = noOfDaysLeft();
final int degrees = getDregeesFordays(totalDays() - noOfDaysLeft);
textView.setText(noOfDaysLeft() + "\nday" + (noOfDaysLeft() == 1 ? "" : "s"));
mProgress.setProgress(degrees);
}
here is date
"startDate": "2019-09-12T15:48:12.293Z",
"endDate": "2019-10-12T08:19:00.710Z",
i want to set progress based on multiple of 3 like if we have days diff is 1,2,3 then it should show same progress then 4,5,6 then it less secondly progress and so on ...
Get epoch time in unit of seconds. I use OffsetDateTime(ThreeTen).
val offset = OffsetDateTime.now().offset
val startDateEpoch = [your starting date in LocalDateTime unit].toEpochSecond(offset)
val endDateEpoch = [your end date in LocalDateTime unit].toEpochSecond(offset)
Calculate result = endDateEpoch - startDateEpoch
Translate it to days
eg. result = 500000
timeDifference = result / (3600 * 24)
... additional algorithm
Conditional check for progressBar
if(timeDifference >= 1 && timeDifference <= 3) doA()
else if(timeDifference >= 4 && timeDifference <= 7) doB()
...additional algorithm
Update : How to build LocalDateTime unit
val dayOfMonth = 23
val year = 2001
val month = 3
val hour = 0
val minute = 0
val myDate = LocalDate.of(year, month, dayOfMonth)
val myTime = LocalTime.of(hour, minute)
val startDateTime = LocalDateTime.of(myDate, myTime)

Android - Check if current time is between 2 given times and the day of the week is valid

I have to take an action if the time falls between start and stop time and on a specific day. I referred some existing threads on SO to check if the time falls within the specified time range.
Say if start time is 23:00pm, stop time is 7:00am and current time is 2:00am. Just the time validity function returns true. But if I include days in this code, the function returns false. Eg: user selects [Monday, Tuesday, Wednesday]. Even though Thursday is not in the list, but the end time 7:00am falls on Thursday, action can be taken anytime between 23:00pm Wed - 7:00am Thu, but action cannot be taken on 23:00pm Thu or any days not mentioned in the list.
Below is my code:
private fun isCurrentTimeBetweenProvidedTime(context: Context): Boolean {
var reg = "^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$".toRegex()
val startTime = getStartTime()
val endTime = getEndTime()
val currentTime = getCurrentTime()
if (reg.containsMatchIn(startTime) && reg.containsMatchIn(endTime) && reg.containsMatchIn(currentTime)) {
var valid = false
var startTime = SimpleDateFormat("HH:mm:ss").parse(startTime)
var startCalendar = Calendar.getInstance()
startCalendar.time = startTime
var currentTime = SimpleDateFormat("HH:mm:ss").parse(currentTime)
var currentCalendar = Calendar.getInstance()
currentCalendar.time = currentTime
var endTime = SimpleDateFormat("HH:mm:ss").parse(endTime)
var endCalendar = Calendar.getInstance()
endCalendar.time = endTime
if (currentTime.compareTo(endTime) < 0) {
currentCalendar.add(Calendar.DATE, 1)
currentTime = currentCalendar.time
}
if (startTime.compareTo(endTime) < 0) {
startCalendar.add(Calendar.DATE, 1)
startTime = startCalendar.time
}
if (currentTime.before(startTime)) {
valid = false
} else {
if (currentTime.after(endTime)) {
endCalendar.add(Calendar.DATE, 1)
endTime = endCalendar.time
}
if (currentTime.before(endTime)) {
valid = true
} else {
valid = false
}
}
// This won't work if day is Thursday and time is 2:00am, even though time falls between 23:00-7:00
var todayCalendar = Calendar.getInstance()
if ((currentTime >= startTime && todayCalendar.get(Calendar.DAY_OF_WEEK) in selectedDays.values) &&
(currentTime <= endTime && (todayCalendar.get(Calendar.DAY_OF_WEEK) in selectedDays.values || todayCalendar.get(Calendar.DAY_OF_WEEK)-1 in selectedDays.values))) {
Log.d(TAG, "Days are valid")
}
return valid
}
return false
}
How do I handle the days scenario?
java.time and ThreeTenABP
Please note: This code can work on Android API levels both under and over level 26. I will explain further down. I will have to trust you to translate from Java code.
If I have understood your requirements correctly:
ZoneId zone = ZoneId.of("America/Chihuahua");
LocalTime startTime = LocalTime.of(23, 0);
LocalTime endTime = LocalTime.of(7, 0);
Set<DayOfWeek> selectedDays
= EnumSet.of(DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY);
ZonedDateTime now = ZonedDateTime.now(zone);
LocalTime timeNow = now.toLocalTime();
DayOfWeek currentDayOfWeek = now.getDayOfWeek();
boolean inIntervalOnDay;
if (startTime.isAfter(endTime)) { // crosses midnight
if (timeNow.isBefore(endTime)) { // in interval, after midnight
// Day is correct if the day before is among the selected days
inIntervalOnDay = selectedDays.contains(currentDayOfWeek.minus(1));
} else if (timeNow.isBefore(startTime)) {
inIntervalOnDay = false;
} else { // after start time, before midnight
inIntervalOnDay = selectedDays.contains(currentDayOfWeek);
}
} else {
inIntervalOnDay = ! timeNow.isBefore(startTime)
&& timeNow.isBefore(endTime)
&& selectedDays.contains(currentDayOfWeek);
}
System.out.println("Now: " + now + " (" + currentDayOfWeek + ") Valid? " + inIntervalOnDay);
When I ran the snippet just now, the output was:
Now: 2019-09-27T03:47:56.856-06:00[America/Chihuahua] (FRIDAY) Valid? false
Please substitute your desired time zone if it didn’t happen to be America/Chihuahua. Time zone matters.
Question: Can I use java.time on Android below API level 26? How?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
One possible approach could be to normalize all your times to offsets from a chosen week starting point, say Sunday 12:00am = 0. Convert all your times into minutes since the starting point. Then simply check whether your chosen time (also converted to minutes since start) falls within any of the ranges.

Difficulty getting data from Sqlite database between two days

I was doing an Android app that generates sales report for dates between the current date and seven days in the past. It worked fine, here's the code:
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR,-7);
String currentDate = new SimpleDateFormat("dd-MM-yyyy").format(new Date());
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
String sevenDayAgo = sdf.format(calendar.getTime());
Cursor weeklyIncome = db.getResult("select sum(price) as total_income from sales where date between '"+sevenDayAgo+"' and '"+currentDate+"'");
Cursor weeklyCost = db.getResult("select sum(purchase_price * quantity) as total_cost from sales where date between '"+sevenDayAgo+"' and '"+currentDate+"'");
Say for example currentDate = 31-08-2018 and sevenDayAgo = 24-08-2018 this all worked fine but when I change my system date to the next day which is the next month and currentDate becomes 01-09-2018 the query doesn't return anything from the database, it should have returned records between 25-08-2018 and 01-09-2018 which has seven days in between. Somehow the query doesn't work when the 7 days are in two different months. I don't know what's going on and how to fix it.
p.s. The date column in sales table is of type TEXT.
The problem is the format you're using for dates (dd-mm-yyyy) isn't in lexicographic order. The string '25-08-2018' compares greater than '01-09-2018' . x BETWEEN y AND z is equivalent to x >= y AND x <= z. That condition won't be true for dates in that range using your format (Remember, they're just strings. sqlite does not have a date type.
You should be using ISO-8601 formats, like yyyy-mm-dd. These will sort properly ('2018-08-25' < '2018-09-01') and will allow you to use the sqlite3 date and time functions on them.
Suppose user has entered the birth date in 31/08/2018 this format :
Parse it like :
String[] parts = BirthField.getText().toString().trim().split("/");
int CAL_DAY, CAL_MONTH, CAL_YEAR;
if(parts.length == 3)
{
CAL_DAY = Integer.parseInt(parts[0]);
CAL_MONTH = Integer.parseInt(parts[1]);
CAL_YEAR = Integer.parseInt(parts[2]);
}
You can check if user has entered a good date or not with :
if( CAL_DAY > 0 && CAL_DAY < 32 && CAL_MONTH > 0 && CAL_MONTH < 13 && CAL_YEAR > 1900 )
While storing in database table take below care :
Calendar CalendarEvent = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
CalendarEvent.set(Calendar.DATE, CAL_DAY);
CalendarEvent.set(Calendar.MONTH, CAL_MONTH - 1);
CalendarEvent.set(Calendar.HOUR_OF_DAY, Integer.parseInt(ScheduleTime) );
CalendarEvent.set(Calendar.MINUTE, 00);
CalendarEvent.set(Calendar.SECOND, 00);
SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.getDefault());
String DayConsidered = format.format(CalendarEvent.getTime());
Please note CAL_MONTH - 1 as system starts months from 0 to 11
While storing store in database in SystemTime like :
SYSTIME = CalendarEvent.getTimeInMillis();
While using it again retrieve it from database and initialise calendar event with it like :
Calendar CalendarEvent = Calendar.getInstance();
CalendarEvent.setTimeInMillis( Long.parseLong(SYSTIME) );
int CAL_DAY = CalendarEvent.get(Calendar.DAY);
CalendarEvent.set(Calendar.DATE, CAL_DAY - 7);
And it will start working for even if days / months / even you change years from any date; it will always show the date which is less than 7 days
Hope it helps and let me know how it works as i am answering it quick...
Edit : 2
Better and most efficient way which i am using in my project and working perfectly is :
Log.d("ADDING A MONTH :", "ADDING 1 MONTH....\n");
CalendarEvent.add(Calendar.MONTH, 1);
Log.d("NEGATING 7 DAYS :", "NEGATING 7 DAYS....\n");
CalendarEvent.add(Calendar.DATE, -7);

Change DateFormat depending on Days passsed

Essentially what I have is a string which contains a files Last Modified Date. To get this I'm using:
Date lastModDate = new Date(file.lastModified());
SimpleDateFormat formatter = new SimpleDateFormat("K:mm a");
String formattedDateString = formatter.format(lastModDate);
The end result is somewhat like 6:12 AM. What I want to do is each time a certain period of time is passed, the dateformat must change. E.g.
After 1 Day has gone by, Last Modified Date = ("Format1");
After a Week has gone by, Last Modified Date = ("Format2");
After 2 Weeks have gone by, Last Modified Date = ("Format3");
Does it make sense? If so is someone please be able to show me how it's done. A good example is the native Messaging App. When a message is created, It will show it's Time then after some days gone by the format changes to the Date it was created then the month etc...
I'm trying to do exactly that.
Calculate the difference in time between the last modified date and now:
long duration = lastModDate.getTimeInMillis() - current.getTimeInMillis();
long sec = TimeUnit.MILLISECONDS.toSeconds(duration);
boolean inFuture = sec > 0;
// Use positive value
if(!inFuture)
sec = -sec;
long minutes = sec / 60 % 60;
long hours = sec / 3600 % 24;
long days = sec / 86400;
if(days > 1 && days < 7)
// Use format 1
else if(days >= 7 && days < 14)
// Use format 2
else
// Use format 3

Anyway of using before time function and equal to?

i am using the code below:
endTimeEntryCal2.before(addTimeEntryCale)
to check if user set time is before current time but i also want it to be before or equal to is there anyway of doing this here eg something like before=();
This does the trick:
endTimeEntryCal2.compareTo(addTimeEntryCale) <= 0
int compareTo(Calendar anotherCalendar)
Compares the times of the two Calendar, which represent the
milliseconds from the January 1, 1970 00:00:00.000 GMT (Gregorian).
Parameters anotherCalendar another calendar that this one is compared with
Returns:
0 if the times of the two Calendars are equal,
-1 if the time of this Calendar is before the other one
1 if the time of this Calendar is after the other one.
long mills = cal.getTimeInMillis();
long currentTime = System.currentTimeMillis();
int x = (mills <= currentTime)?0:1;
if(x == 1)
{
// Time Available
}else
{
//Time passed
}

Categories

Resources