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
}
Related
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.
I have an application that tracks the wait time of a customer in a restaurant. It simply subtracts the time the customer began waiting from the current time, then formats it with StandardDateFormat into hh:mm and displays it as a string.
The problem is that the timer always begins with 6 hours, such as 06:01.
ActionListener actListner = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
aTable.updateTime();
}
};
Timer timer = new Timer(1000, actListner);
timer.start();
}
This is in the main program
public void updateTime()
{
data.updateTime();
fireTableDataChanged();
fireTableRowsInserted(data.name.size() - 1, data.name.size() - 1);
}
This is in the table model
public void updateTime()
{
Date newTime = new Date();
for (int i = 0; i < startTime.size(); i++)
{
this.setTimeWaiting(i, hoursMin.format(new Date(newTime.getTime() - startTime.get(i).getTime())));
}
}
public void setTimeWaiting(int index, Object newVar)
{
timeWaiting.remove(index);
timeWaiting.add(index, newVar.toString());
}
This is in the data model.
Every time a new row is added it puts the time the row is added in one column then the time that person has been waiting in the other column, but the waiting column is 6 hours ahead. It otherwise works fine.
This sounds like a timezone issue. Maybe you should set the timezone for the date format to UTC.
As k_g says, this is almost certainly a time zone issue. You are getting funny results because the Date class is intended for absolute times, not intervals.
I would recommend you use a library like Joda Time. It has special classes for concepts such as Intervals and Durations.
Or if you are using JDK 8 you can use the new date/time classes that have just been introduced.
I am working on a project that will run many thousands of comparisons between dates to see if they are in the same month, and I am wondering what the most efficient way of doing it would be.
This isn't exactly what my code looks like, but here's the gist:
List<Date> dates = getABunchOfDates();
Calendar month = Calendar.getInstance();
for(int i = 0; i < numMonths; i++)
{
for(Date date : dates)
{
if(sameMonth(month, date)
.. doSomething
}
month.add(Calendar.MONTH, -1);
}
Creating a new Calendar object for every date seems like a pretty hefty overhead when this comparison will happen thousands of times, soI kind of want to cheat a bit and use the deprecated method Date.getMonth() and Date.getYear()
public static boolean sameMonth(Calendar month, Date date)
{
return month.get(Calendar.YEAR) == date.getYear() && month.get(Calendar.MONTH) == date.getMonth();
}
I'm pretty close to just using this method, since it seems to be the fastest, but is there a faster way? And is this a foolish way, since the Date methods are deprecated? Note: This project will always run with Java 7
I can't comment on whether to use the deprecated methods, but if you choose not to there's no need to instantiate a new Calendar for every Date you check. Just use one other Calendar and call setTime(date) before the check (or one Calendar for every thread if you parallelize it).
As a side note, I do have to agree with ChristopheD's comment that this is something worthy of a database.
I think you can define a static DateFormat to extract the month and year from Date and use both objects as date only.
public static DateFormat formatter= new SimpleDateForm("MMyyyy");
public static boolean sameMonth(Date date1, Date date2)
{
return formatter.format(date1).equals(formatter.format(date2));
}
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;
}
I have a list of objects called Activity:
class Activity {
public Date activityDate;
public double amount;
}
I want to iterate through List, group them by date and return a new list . Here's what I currently do:
private List<Activity> groupToList(List<Activity> activityList) {
SimpleDateFormatter sdf = new SimpleDateFormatter("YYYY-MM-DD");
Map<String,Activity> groupMap = new HashMap<String,Activity>();
for (Activity a in activityList) {
String key = sdf.format(a.getActivityDate());
Activity group = groupMap.get(key);
if (group == null) {
group = new Activity();
groupMap.add(key, group);
}
group.setAmount(group.getAmount() + a.getAmount());
}
return new ArrayList<Activity>(groupMap.values());
}
Is it a WTF to use the DateFormatter in this way?
I'm using the DateFormatter because each activityDate could have time information.
I would just use the date object itself as the key. If it it bothers you because the date object is mutable, then use its toString() value. No reason to go making formats.
If the issue is that you want to normalize the date by removing the time component, it would be much better to do that withing the Activity object and remove the time component. If the issue is still further that there are potential time zone issues, I would use JodaTime, but there is no object in the JDK currently that represents a pure date without time, so going with a string isn't outrageous, but it should be hidden behind a method in the Activity object and the fact that it is a date formatted string without a time component should be an implementation detail.
java.util.Date is a quite poor abstraction for your need; it is IMO fair to stick to strings if nothing better is around, HOWEVER Joda-time provides a good datatype for you: DateMidnight or alternatively LocalDate if Activity is strictly timezome-independant.
other than that, the code looks good to me, you might be able to shorten it a bit using an implementation of Multimap, to avoid messy null-checking code. to be honest, it doesn't get much shorter than your solution:
public List<Activity> groupedByDate(List<Activity> input) {
//group by day
final Multimap<DateMidnight, Activity> activityByDay
= Multimaps.index(input, new Function<Activity, DateMidnight>() {
#Override
public DateMidnight apply(Activity from) {
return new DateMidnight(from.activityDate);
}
});
//for each day, sum up amount
List<Activity> ret = Lists.newArrayList();
for (DateMidnight day : activityByDay.keySet()) {
Activity ins = new Activity();
ins.activityDate = day.toDate();
for (Activity activity : activityByDay.get(day)) {
ins.amount+=activity.amount;
}
}
return ret;
}
Why not simply create a HashMap<Date, Activity>() instead of the roundabout way with Strings?
Sorry, I didn't answer the question. The answer is: yes, unless I am an idiot ;)
You could do this using the Date as the key if you used a TreeMap and provided a Comparator that only compared the year, month and day and not the time.
As already mentioned the best solution is to represent your date with day precission. If this is not possible joda is nice library.
If you can ignore daylight saving time then grouping by date can be accomplished much easier. A unix time day is 86 400 s long. The timestamp does ignore leap seconds. (Your timer stops for one second or the leap second is distributed in some way.) All date values were day is equal are the same day:
int msPerDay = 86400 * 1000;
long day = new Date().getTime() / msPerDay
One minor point is to adjust the timezone. For my timezone CET (UTC/GMT +1 hour) the GMT day starts one our later:
new GregorianCalendar(2009, 10, 1, 1, 0).getTime().getTime() / msPerDay) ==
new GregorianCalendar(2009, 10, 2, 0, 59).getTime().getTime() / msPerDay) ==
new Date().getTime() / msPerDay
If the daylight saving time is significant the best way is to use joda. The rules are just to complicated and locale specific to implement.