I'm trying to make a app which includes telling the time of next Thursday. App crashes every time i open that class.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_authorised);
button.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
nextThursday();
}
});
}
void nextThursday(){
String nextThursday = getNext(DayOfWeek.THURSDAY).format(DateTimeFormatter.ofPattern("MMM, dd yyyy", Locale.ENGLISH));
nextThurs.setText(nextThursday);
}
public static LocalDate getNext(DayOfWeek dayOfWeek) {
// get the reference day for the word "next" (that is the current day)
LocalDate today = LocalDate.now();
// start with tomorrow
LocalDate next = today.plusDays(1);
// as long as the desired day of week is not reached
while (next.getDayOfWeek() != dayOfWeek) {
// add one day and try again
next = next.plusDays(1);
}
// then return the result
return next;
}
}
Is anyone able to help?
This answer uses java.time, which is the datetime API to be used since the Joda Time project stopped further development.
It basically uses an algorithm that may be realizable in Joda Time, too, but I don't know exactly if and how, so I show you a way in java.time.
Define a method that returns the date of the next given day of week:
public static LocalDate getNext(DayOfWeek dayOfWeek) {
// get the reference day for the word "next" (that is the current day)
LocalDate today = LocalDate.now();
// start with tomorrow
LocalDate next = today.plusDays(1);
// as long as the desired day of week is not reached
while (next.getDayOfWeek() != dayOfWeek) {
// add one day and try again
next = next.plusDays(1);
}
// then return the result
return next;
}
and use it in a main() just to print it out:
public static void main(String[] args) {
System.out.println("Next Thursday is " +
getNext(DayOfWeek.THURSDAY)
.format(DateTimeFormatter.ofPattern("MMM, dd yyyy", Locale.ENGLISH)));
}
which results in the output when executed Friday, 15th of May 2020:
Next Thursday is May, 21 2020
Of course, the format is just an example and can easily be adjusted according to your needs.
It's quite simple using a predefined TemporalAdjuster:
LocalDate date = LocalDate.now()
.with(TemporalAdjusters.next(DayOfWeek.THURSDAY));
This is natively supported since Java 8 or Android API level 26. To target previous API levels, use the ThreeTen Android Backport.
Joda Time is in maintenance mode, and they're suggesting that you use java.time instead.
Deleted all code in that activity. Still crashed. Error was not in the code. Something else got messed up instead.
Related
I am trying to calculate the age of the person based on the date of birth and doing some logic if its over 18 years. I had my code written and it was working fine, but I stumbled upon a code I found online and I am not getting one condition in that. The code is:
public class AgeValidation {
public static void main(String[] args) {
getAge("29-12-1999");
}
private static void getAge(String dob1) {
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
Date dob;
try {
dob = format.parse(dob1);
Calendar dob2 = Calendar.getInstance();
dob2.setTime(dob);
Calendar today = Calendar.getInstance();
int age = today.get(Calendar.YEAR) - dob2.get(Calendar.YEAR);
if(dob2.after(today)) {
System.out.println("Future date not allowed");
System.exit(0);
}
if (today.get(Calendar.MONTH) < dob2.get(Calendar.MONTH)) {
System.out.println("First if condition");
age--;
} else if (today.get(Calendar.MONTH) == dob2.get(Calendar.MONTH)
&& today.get(Calendar.DAY_OF_MONTH) < dob2.get(Calendar.DAY_OF_MONTH)) {
System.out.println("else if condition");
age--;
}
if (age < 18) {
System.out.println(age);
System.out.println("Underage");
} else {
System.out.println(age);
System.out.println("18 years");
//Some logic
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}
Need addressing on below points:
I have added a condition if DOB year is after Current year it should not proceed.
if(dob2.after(today)) {
System.out.println("Future date not allowed");
System.exit(0);
}
Is it correct to use System.exit(0); or is there some better approach to stop further execution.
In the code that I found online I saw a condition as
` if (today.get(Calendar.MONTH) < dob2.get(Calendar.MONTH))`
I am not getting in which scenario will this be executed.
Is there any use case in which this code will not work (I cannot think of any)
java.time
You should not (as in not) want to use the long outdated classes SimpleDateFormat, Date and Calendar. Especially the first is notoriously troublesome, but we have better replacements for all of them in java.time, the modern Java date and time API also known as JSR-310.
And even more so because the modern API has a method for counting years between two dates built-in. Not only is it easier to write the code, more importantly it is easier to read and understand, and you can be more sure of the correctness.
private static final DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("dd-MM-uuuu");
private static void getAge(String dob1) {
LocalDate dob = LocalDate.parse(dob1, dateFormatter);
LocalDate today = LocalDate.now(ZoneId.of("Asia/Dushanbe"));
if (dob.isAfter(today)) {
System.out.println("Future date not allowed");
} else {
int age = (int) ChronoUnit.YEARS.between(dob, today);
if (age < 18) {
System.out.println(age);
System.out.println("Underage");
} else {
System.out.println(age);
System.out.println("18 years");
//Some logic
}
}
}
With your example date of "29-12-1999" the above method prints:
17
Underage
Since it is never the same date in all time zones, please substitute your desired time zone instead of Asia/Dushanbe.
between() returns a long. In this case we can safely cast it to an int because LocalDate only handles years in the range -999 999 999 through 999 999 999, so the difference in years will never exceed the capacity of int.
Your questions
Use of System.exit(0); is generally questionable, though at times necessary. In my code I have avoided it using an if-else construct. Another option would be return;. I guess this would more give you what you wanted in case there were two calls to getAge() after each other. Yet another option is throwing an IllegalArgumentException, that would leave for the caller to decide to catch it or not.
The line you are quoting will not be executed when running your code here in December. Imagine running your code next January, then today’s month will be January and dob2’s month will still be December, so since January is before December, the code will be executed. Which will also be necessary for your method to calculate the correct age.
The code seems convoluted, as Jim Garrison said, but appears to be correct (not even with the outdated API needed it be this complex). I have not spotted a case that would not be handled correctly.
Question: Can I use the modern API with my Java version?
If using at least Java 6, you can.
In Java 8 and later the new API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310).
On Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP, and there’s a thorough explanation in this question: How to use ThreeTenABP in Android Project.
For learning to use java.time, see the Oracle tutorial or find other resoureces on the net.
I am giving you a solution which doesn't take care of leap year logic. But you can build upon this approach.
public static void main(String[] args) throws Exception{
String date ="11_10_1991";
SimpleDateFormat sdf = new SimpleDateFormat("dd_MM_yyyy");
Date birthDate = sdf.parse(date);
long ageInMillis = System.currentTimeMillis() - birthDate.getTime();
long years = ageInMillis /(365 * 24*60*60*1000l);
long leftover = ageInMillis %(365 * 24*60*60*1000l);
long days = leftover/(24*60*60*1000l);
System.out.println(years);
System.out.println(days);
}
How do i check if a period of time(consisting of two temporal timevalues(start and end)) passes for example midnight ?
Im trying to use the LocalDateTime class, but can't seem to find anything usefull there..
This is the best I can come up with:
public static boolean passesTime(LocalDateTime start,
LocalDateTime end,
LocalTime time) {
// If the duration is more than a day, any time will be passed.
if (Duration.between(start, end).toDays() >= 1)
return true;
// Otherwise, the time has to be passed on the start day...
LocalDateTime timeOnStartDay = LocalDateTime.of(start.toLocalDate(), time);
if (timeOnStartDay.isAfter(start) && timeOnStartDay.isBefore(end))
return true;
// or on the end day.
LocalDateTime timeOnEndDay = LocalDateTime.of(end.toLocalDate(), time);
if (timeOnEndDay.isAfter(start) && timeOnEndDay.isBefore(end))
return true;
return false;
}
Tested with the java.time API. If you're using Joda time the code should be similar (if not identical).
I'm about to write lines of some simple math and wanted to make sure that there wasn't some simple high level construct in Joda-Time to do this already.
I have an object that represents a day of the week, an hour of the day, and a minute of the hour. For example "Wednesday at 10:14am".
I want to calculate the number of milliseconds until the next occurrence. For example if now is Thursday at 10:14 it would be 6 days worth of milliseconds. This is because Wednesday has already passed so it will take 6 days to get to the next Wednesday. If now is Wednesday at 10:13.0001 it will be 999.
Is there a high level construct in Joda-Time so I can do this in one or two lines of code or do I need to do the math myself (including edge cases to wrap on stuff like DOW < DOW_NOW).
Thanks!
Here's my novice try that does not yet work to give you some reference:
public MutableDateTime getDateTime() {
MutableDateTime date = MutableDateTime.now();
date.setDayOfWeek(this.day);
date.setHourOfDay(this.hour);
return date;
}
public long getTimeUntilNextFrom( DateTime from ) {
MutableDateTime to = getDateTime();
if (to.isBefore( from )) {
to.setWeekOfWeekyear(from.getWeekOfWeekyear() + 1);
}
return new Interval(from, to).toDurationMillis();
}
You could do something like this:
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.Interval;
import org.joda.time.LocalTime;
public class Main {
public static void main(String[] args) {
Interval interval = betweenNowAndNext(DateTimeConstants.MONDAY, new LocalTime(10, 14));
System.out.println(interval.toDurationMillis());
}
public static Interval betweenNowAndNext(int dayOfWeek, LocalTime time) {
DateTime now = DateTime.now();
DateTime closest = time.toDateTime(now).withDayOfWeek(dayOfWeek);
return new Interval(now, closest.isBefore(now) ? closest.plusWeeks(1) : closest);
}
}
I would do it like this:
public class DistanceCalculator {
public long getMillisecondTillNext(int dayOfWeek, int hourOfDay, int minuteOfHour) {
DateTime now = DateTime.now();
DateTime next = DateTime.now().withDayOfWeek(dayOfWeek).withHourOfDay(hourOfDay).withMinuteOfHour(minuteOfHour);
long distance = next.getMillis() - now.getMillis();
return distance > 0 ? distance : week() - distance;
}
private long week() {
return new DateTime(0).plusWeeks(1).getMillis();
}
}
Haven't hear of any readymade method to get this in Joda...
Here's what I came up with on my own. Still, would be nice to have a solution in fewer lines of code. They DayHour is the class I am working with. It contains a day of the week and the hour of the day.
public class DayHour {
int day;
int hour;
public DayHour(int day, int hour) {
this.day = day;
this.hour = hour;
}
public MutableDateTime getDateTime(DateTime base) {
MutableDateTime date = base.toMutableDateTime();
date.setDayOfWeek(this.day);
date.setHourOfDay(this.hour);
return date;
}
public long getTimeUntilNextFrom(DateTime from) {
MutableDateTime to = getDateTime(from);
if (to.isBefore(from)) {
to.setWeekOfWeekyear(from.getWeekOfWeekyear() + 1);
}
return new Interval(from, to).toDurationMillis();
}
}
#Test
public void testDayHour() {
DateTime now = DateTime.now();
DayHour date = new DayHour(now.getDayOfWeek(), now.getHourOfDay());
MutableDateTime yesterday = now.toMutableDateTime();
yesterday.addDays(-1);
assertEquals(TimeUnit.DAYS.toMillis(1), date.getTimeUntilNextFrom(yesterday.toDateTime()));
MutableDateTime tomorrow = now.toMutableDateTime();
tomorrow.addDays(1);
assertEquals(TimeUnit.DAYS.toMillis(6), date.getTimeUntilNextFrom(tomorrow.toDateTime()));
}
Not quite sure what you are doing. But if what you want is a countdown in milliseconds, I would use the Joda-Time Seconds class with its secondsBetween method. Multiply by 1,000 to report approximate milliseconds. On the last second, switch gears to use the .getMillis method if you truly need that.
I am trying to make a digital clock in android.
I looked into the Time and Date classes.
However I cannot find any API that is tells me how to obtain when a minute has passed?
For e.g. when working with locationManagers,
public void onLocationChanged(Location location)
is called when new location is available.
Similarly I am looking for something that is called when time changes, where time is in format hh:mm or hh:mm:ss.
You'll need joda for this code, but you should be using it anyway for anything involving time calculations in Java.
public DateTime date = new DateTime();
public void updateClock {
if (Seconds.secondsBetween(new DateTime(), date).getValue() != 1) {
return;
}
date = new DateTime();
// do your thing
}
Problem: I have a list containg hours, for example:
08:15:00
08:45:00
09:00:00
12:00:00
...
application is allowing user to make an appointment for a specific hour let'say: 8:15:00, each meeting takes half an hour.
Question: How to determine if there is a slot needed for appointment like this? I know that Calendar class have methods before() nad after(), but it doesn'solve my problem. I mean if there is appointment at 12:00 and another one at 12:00, how to prevent before making another one at 12:15?
edit:
I've tried using methods I mentioned before, like:
Calendar cal1 = Calendar.getInstance(); // for example 12:00:00
Calendar cal2 = Calendar.getInstance(); // for exmaple 12:30:00
Calendar userTime = Calendar.getInstance(); // time to test: 12:15:00
if(user.after(cal1)&& user.before(cal2)){
... // do sth
}
Check if the date to check is between the two provided:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm");
Date before = sdf.parse("07/05/2012 08:00");
Date after = sdf.parse("07/05/2012 08:30");
Date toCheck = sdf.parse("07/05/2012 08:15");
//is toCheck between the two?
boolean isAvailable = (before.getTime() < toCheck.getTime()) && after.getTime() > toCheck.getTime();
To book for a determinate hour, I would do a class with two dates and a method to check this:
public class Appointment{
private Date start;
private Date end;
public boolean isBetween(Date toCheck){....}
}
Then you can simply do an Schedule class extending ArrayList, adding a method isDateAvailable(Date toCheck), iterating the list of Appointments and checking that there is no one conflicting.
I'd have some kind of appointment class with either a start timestamp and a duration or a start time and an end time. Then when adding new appointments to the schedule, check that the appointment with the start time before the new appointment doesn't run over the start time of the proposed new appointment.
Well how you would do it specifically depends on how you are storing your data, format, etc., but generally what you would do is simply check if there is an appointment for any time between the requested time to the requested time + requested length.
// Example (using int time(1 = 1 minute), assuming that appointments can only be at 15min intervals)
boolean isHalfHourTimeSlotAvaliable(int time) {
for (int i = 0; i < appointments.size(); i++) {
if (appointments.get(i).time == time || appointments.get(i).time == time + 15) {
return false;
}
}
return true;
}