I have two hours lets say 12:00 and 14:00 (the input will always be two hours of "whatever" day) second time will always be greater than first time. So the input is simple : two given times in a day. I need to find every 30 minutes between those two times.
I need the following output (the ellapsed time between each output will always be 30 minutes in my case:
12:00
12:30
13:00
13:30
14:00
14:30
I am discovering jodatime but I am a bit confused with how the determine "startTime" and "end Time"
It's pretty easy, actually:
DateTime current = start;
while(true){
System.out.println(current);
current=current.plusMinutes(30);
if(current.isAfter(stop))break;
}
Responding to comment:
to parse a String, you need a DateTimeFormatter. Here's one of several ways to acquire one:
private static final DateTimeFormatter DATE_TIME_FORMATTER =
DateTimeFormat.forPattern("HH:mm");
Now you can do:
DateTime startDate = DATE_TIME_FORMATTER.parseDateTime(startString);
Related
I'm having an issue working with time in Java. I don't really understand how to efficiently solve comparing the time of now and 12 hours before and after
I get a set of starting times for a show from an API and then compare that starting time with LocalTime.now(). It looks something like this:
SimpleDateFormat sdt = new SimpleDateFormat("HH:mm:ss");
String temp = sdt.format(Local.time(now));
LocalTime secondTime = LocalTime.parse(parts1[0]);
LocalTime firstTime = LocalTime.parse(temp);
int diff = (int) ((MINUTES.between(firstDay, secondDay) + 1440) % 1440);
if(diff <= 720){
return true;
}
Where my idea is that if the difference between the two times is smaller than 720 minutes (12 hours) I should get the correct output. And this works for the 12 hours before now. I thought I might need to swap the parameters of .between, to get the other side of the day. That counts it completely wrong (If the time now is 15:00:00 it would accept all the times until 22:00:00 the same day). Is this just a really bad way of comparing two times? Or is it just my math that lacks understanding of what I'm trying to do?
Thanks
Using the 'new' (not that new) Java 8 time API:
Instant now = Instant.now();
Instant hoursAfter = now.plus(12, ChronoUnit.HOURS);
Instant hoursBefore = now.minus(12, ChronoUnit.HOURS);
First, doing this kind of operations on java.time.LocalTime won't work! Or at least only if the time is "12:00:00" …
That is because you will have an over-/underflow when you add/substract 12 hours from any other time.
So your starting point should be to go for java.time.LocalDateTime (at least, although I would go for java.time.Instant). Now you can handle the over-/underflow, as you will get another day when adding or subtracting 12 hours.
How this works is shown in this anwswer: LocalDateTime allows nearly the same operations as Instant.
I've found an issue about Java DST change.
When the exact moment that DST(Daylight Saving time) happened, the certain time may appears two times.
For example, for the timezone America/Sao_Paulo, it changed backward one hour from Sunday, 21 February 2016, 00:00:00 to Saturday, 20 February 2016, 23:00:00.
The time 23:00 appears twice that day.
In my use case, I'd like to take the second time. For example, when I want the data of this day, I actually mean this day completely (even if maybe it contains 25 hours).
But in my opinion, it seems that Java take the first time of this moment.
Example:
#Test
public void testDSTChange() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
TimeZone tz = TimeZone.getTimeZone("America/Sao_Paulo");
long dateInput = sdf.parse("2016-02-20T23:00:00").getTime();
long dateUTC = dateInput - tz.getOffset(dateInput);
long dateInput2 = sdf.parse("2016-02-21T02:00:00").getTime();
long dateUTC2 = dateInput2 - tz.getOffset(dateInput2);
System.out.println("Difference: " + (dateUTC2 - dateUTC) / 3600 / 1000);
}
In this example, it shows that the difference between these two dates is 4 hours, not the 3 hours that I expected. So I wonder that if there's any other way to do it ?
Well, the time at the DST change will occur twice when the DST changes backward, there is no way around it. There may be another way around, but let me make a suggestion, internally use UTC time (GMT) it has no DST internally, convert to local time (wall clock time) on output for display purposes only. You will never have to worry about it again.
In my use case, I'd like to take the second time. For example, when I want the data of this day, I actually mean this day completely (even if maybe it contains 25 hours).
From this statement, I'll assume you are actually doing some kind of range query to gather data over the entire day. The best way to approach this is to query from the start of the day inclusive, to the start of the next day exclusive. In other words: startOfDay <= dataPoint(s) < startOfNextDay
This works well in your scenario, because the clock doesn't actually hit 00:00 until the next day has started. It ticks like this:
23:58
23:59
23:00
23:01
...
23:58
23:59
00:00 <--- start of next day
So use half-open intervals, and it should just work out.
Do be careful in the spring transition though, when the start of the day is 01:00, not 00:00. :)
Also, Jon's comment about using Java 8's new time APIs, or Joda-Time are spot-on. They both offer you better control over this situation. Older Java APIs do not.
LocalDateTime l1 = LocalDateTime.of(2016, Month.FEBRUARY, 20, 23, 0, 0);
ZoneId id = ZoneId.of("America/Sao_Paulo");
ZoneOffset offset = ZoneOffset.of("-08:00");
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(l1, offset, id);
long el1= zonedDateTime.toEpochSecond();
LocalDateTime l2 = LocalDateTime.of(2016, Month.FEBRUARY, 21, 2, 0, 0);
ZonedDateTime zonedDateTime1 = ZonedDateTime.ofInstant(l2, offset, id);;
long el2= zonedDateTime1.toEpochSecond();
System.out.println("Difference: " + (el2-el1 ) / 3600 );
====================================
on console it prints
Difference: 3
everyone.
I'm trying to figure out if Google Datastore is the best option in my case..
I need to store employees with theirs schedules like:
id
name
schedule
Schedule looks like:
Mon 10am-10pm (simple)
Tue 10am-5pm, 5.30pm-8pm (multiple, not even hours)
..
Sun 6pm-4am (start/end are in different days)
one of the APIs returns if employee is working NOW or not
I tried to play with datastore but GQL queries appeared to be very limited, for example you cant compare in one query two different properties (like
.. WHERE current_time>start_time AND current_time<close_time
You cannot use inequality operators (less than, more than, etc.) on
different property names in the same query.
It means that I need to load lots of entities into my backed and parse them, wasting time and resources.. instead of getting results right from database
Is there any way to use datastore for my task? or its better to go sql?
how to design my database to store schedules in datasore/sql?
thanks in advance!
Based on your examples, I'm going to assume work shifts are in 30 min increments. If that is not the case you can adjust the below easily, although you may want to consider some optimizations.
The below solution will give you constant time look-ups for employees, regardless of how many shifts they work. It also seamlessly handles shifts that go from one day to the next.
0. Your entity model
I'm going to use the following straw man entity
Entity Kind: Employee
- id: Auto id
- name: string
- schedule: repeated integer, indexed
2. Break day into 30 minute blocks
24 hours gives you 48 periods of 30 minutes, so let's map integers to time periods:
0 = 12:00 AM to 12:30 AM
30 = 12:30 AM to 1:00 AM
60 = 1:00 AM to 1:30 AM
...
1380 = 11:00 PM to 11:30 PM
1440 = 11:30 PM to 12:00 AM
This integer is easy to derive from your current time. Using java.util.Calendar and java.util.Date:
Date date = new Date(); // Initializes to now.
Calendar calendar = GregorianCalendar.getInstance();
calendar.setTime(date);
int hour = calendar.get(Calendar.HOUR_OF_DAY); // Hour in 24h format
int minute = calendar.get(Calendar.MINUTE); // Minute of the hour
int period = hour*60 + minute/30*30; // Integer division rounds down to nearest 30
I tested this on compilejava.net, test code here: https://gist.github.com/55a98bbdb9b5eb3eeaee5f8984f11687
3. Account for day of week
Now we have 30 minute period blocks in the day, we should merge in the day of the week (Sunday = 0, Saturday = 6). Since the max 30 min period value is 1440, it is convenient to just multiple the day of the week by 10000 so we can add them together without conflict:
int day = calendar.get(Calendar.DAY_OF_WEEK);
int day_period = day*10000 + period;
Expanded test code here: https://gist.github.com/217221e03b3eb143b4be45bf3f641d25
4. Storing the Schedule
Now, instead of storing your schedule as start and stop times per day, use the same idea above to store each 30 minute period that an Employee is scheduled for. In your example you had:
Mon 10am-10pm (simple)
Tue 10am-5pm, 5.30pm-8pm (multiple, not even hours)
..
Sun 6pm-4am (start/end are in different days)
In the schedule field (repeated integer), this would look like:
10600,10630,10660,10690,10720,10750,10780,10810,10840,10870,10900,10930,10960,10990,11020,
11050,11080,11110,11140,11170,11200,11230,11260,11290,20600,20630,20660,20690,20720,20750,
20780,20810,20840,20870,20900,20930,20960,20990,21050,21080,21110,21140,21170,1080,1110,
1140,1170,1200,1230,1260,1290,1320,1350,1380,1410,0,30,60,90,120,150,180,210
5. Query time!
Querying is extremely easy now and merely an equality. This will give you O(1) performance per Employee entity working right now, or more generally O(n) where n is the number of employees that are working now (as opposed to total employees).
... WHERE schedule=day_period
You can store long representation of the start time and end time. 1 hour = 3600000 milliseconds. So if 00-00 is the reference point 02-00 will be represented by 2 x 3600000 . Another option is to store java.util.Date (one for start time and one for end time)
Two Dates are given:
Let's say,
Date dt1 = 22 June 2013 8:00 PM
Date dt2 = 24 June 2013 6:00 AM
Given the two dates, I want to determine that how many segments from 1 am to 5 am are between these two dates.
For above, there are two segments:
23 June 1 am to 5am
24 June 1am to 5am
So the answer should be 2.
I can get the difference between the two times,
var time1 = new Date(dt1).getTime();
var time2 = new Date(dt2).getTime();
var diff = new Date(time1 - time2);
And the number of hours, min and seconds,
var hours = diff.getHours();
var minutes = diff.getMinutes();
var seconds = diff.getMinutes();
But this only gives difference as expected.
What approach is needed to do so ?
Like everything else in computer science: break the problem down into a series of smaller problems that you're able to solve.
For example, in this problem you might simply determine if there's at least one of your "segments" in the time span. If there is, you might remove the first 24 hours from the full time span, then repeat the process for as long as there exists 24 hours to remove. Remember to count along the way.
Another approach might be to check
if time1.getHours() before or equal to 1am then result=1
if time2.getHours() after 5am then resutl++
result+= diff.getDays() - 1
There is a lot of similar topics but I couldn't find something similar then my problem. I've found only how to calculate if for example second time is greater then first time, like:
22:00
23:00
The result is easy to get. Just subtract second time with first using Date API. Difference is in milliseconds and you can easily convert them in seconds/minutes..
What I want to know, how to get difference between time in first day and time in second day, for example:
22:25
06:30
Difference should be 8 hours and 5 minutes.
Or another example
19:00
00:00
Difference should be 5 hours.
How to calculate time in this way? Any help is appreciated.
Convert your date and time to TimeStamp (It's just the long representation of a date in milliseconds since Jan. 1, 1970.), then calculate difference, and transferred from milliseconds to hours.
Also check this
Use Calendar class. Set your day, hour and minutes and finally subtract those dates (in milliseconds) and you will convert result in hour, minutes and seconds.