Is there any way to download every hour and another period of the day?
I mean exactly the result in the form of a list.
[
"00:00", // start of the day e.q 14.03
"01:00",
"02:00",
....
"23:00",
"00:00 // end of the day e.q 14.03
]
and
[
"00:00", // start of the day e.q 14.03
"00:30",
"01:00"
"01:30"
....
"00:00 // end of the day e.q 14.03
]
and
[
"00:00", // start of the day e.q 14.03
"00:15",
"00:30"
"00:45"
"01:00"
....
"00:00 // end of the day e.q 14.03
]
14.03 means March 14 for the sake of the example.
Of course it is possible to add this manually, but it would not be a particularly elegant solution. Is it possible to do it without explicitly declaring constants as values of each hour ?
The best solution would be a function without using loops and if else constructions.
I have not yet been able to find an implementation of such a solution. I myself also spend another hour on this without success. I need it to implement a functionality that creates a Map or a list of pairs from a list of such e.q hours:
[
"00:00 - 01:00",
"01:00 - 02:00",
"02:00 - 03:00 "
//.......
"23:00 - 00:00"
]
Has anyone had occasion to implement such a problem and would be able to help?
You could write a function to generate a Sequence<LocalTime> like this:
fun generateTimesOfDay(interval: java.time.Duration) = sequence {
if (interval > java.time.Duration.ofDays(1)) {
repeat(2) { yield(LocalTime.MIDNIGHT) }
return#sequence
}
var time = LocalTime.MIDNIGHT
while (true) {
yield(time)
val newTime = time + interval
if (newTime > time) {
time = newTime
} else {
break // passed or reached midnight
}
}
yield(LocalTime.MIDNIGHT) // Midnight the next day to end last period
}
Then you have all the LocalTimes you can use with toString() or with .format() and some DateTimeFormatter to format them how you like. You can use zipWithNext() to create the time ranges.
val x = generateTimesOfDay(java.time.Duration.ofMinutes(15))
println(x.toList())
println(
x.zipWithNext { a, b -> "$a - $b" }.toList()
)
Note, I'm using fully qualified java.time.Duration to avoid conflicts with the Kotlin standard library Duration class.
Related
I am trying to make a list that by default contains a list of available timeslots from one timepoint to another timepoint. It has to avoid making timeslots in a specific timeframe.
For example: I have a first timepoint being 09:00 and the end timepoint being 17:00. The duration of the timeslots is 15. Only sometimes I can't have any time timeslots in a specific timeframe. Which,for example, can be from 12:00 to 12:30.
So eventually the slots should be filled with TimeSlots from 09:00 to 12:00. And from 12:30 to 17:00. This is my code so far, I am using java.time.LocalTime. So far, it's not going that well... Thanks for looking!
data class TimeSlot(
val startTime: LocalTime,
val endTime: LocalTime,
)
private fun initializeSlots(
slots: ArrayList<TimeSlot>,
startTimeShift: LocalTime,
appointmentDuration: Long,
amountOfWorkingHours: Long,
breakTime: LocalTime,
breakDuration: Long
) {
slots.add(TimeSlot(startTime = startTimeShift, endTime = startTimeShift.plusMinutes(appointmentDuration)))
val possibleTotalAppointments = (amountOfWorkingHours * appointmentDuration) - 2 // -2 because index starts at 0 and first timeslot is already added.
for (i in 0..(amountOfWorkingHours * appointmentDuration).toInt()) {
if (slots[i].endTime == breakTime) {
val endTimeOfBreak = breakTime.plusMinutes(breakDuration)
val isTargetWithinTimeFrame = (!breakTime.isBefore(slots[i].startTime) && breakTime.isBefore(endTimeOfBreak))
if (isTargetWithinTimeFrame) {
slots.remove(slots[i])
continue
}
} else {
slots.add(TimeSlot(startTime = slots[i].endTime, endTime = slots[i].endTime.plusMinutes(appointmentDuration)))
}
}
}
If your timeslots are static(Always from 09:00 till 17:00 and always 15 min duration) you can actually hardcode them into an array, and operate through indexes further. So for example if every hour have 4 indexes starting from 0 your specific timeframe 12:00 to 12:30. will have indexes of 12, 13, 14. Such code won't be too beautiful, but still a lot more readable.
Any way, LocalTime is overall not the best idea. I would just use Long, with System.currentTimeMillis() This is the best solution for handling timezones(Formatting them only for UI, not for logic). And also it will make your time calculations much easier, because you can actually divide and subtract millis.
I took another approach to finding the answer, so if anyone comes across the same problem, here it is. You can also give multiple timeframes you want to avoid. Feel free to alter it any way. It can also return Pairs instead of 'TimeSlot's.
fun generateTimeSlots(
startTime: LocalTime,
endTime: LocalTime,
duration: Long,
avoid: List<TimeSlot>
): List<TimeSlot> {
val timeSlots = mutableListOf<TimeSlot>()
var currentTime = startTime
while (currentTime < endTime) {
val nextTime = currentTime.plusMinutes(duration)
val timeSlot = TimeSlot(currentTime, nextTime)
if (avoid.none { timeSlot.startTime in it.startTime..it.endTime.minusMinutes(1) }) {
timeSlots.add(timeSlot)
}
currentTime = nextTime
}
return timeSlots
}
I am using Joda DateTime and have 2 dates :
DateTime old //which is 1:46PM
DateTime new //which is 6:46PM
note: excluded the dates.
How may i be able to loop through the difference in this order :
(print a message for the first half hour, another message for the next 30 minutes and another message per subsequent hour) ?
I was thinking of Subtracting the old date from the new date then make a loop but i don't get the logic. Any pointers will be helpful.
example
If i subtract both times above, i will have an elapsed time of 5 hours.
Loop 5 hours
{
for the first hour (print this)
next 30minutes (print that)
every subsequent hour (print ....)
}
I would use the type LocalTime instead. If you have DateTime as input then please convert it using the method toLocalTime() (with same time and chronology and timezone).
LocalTime start = new LocalTime(13, 46);
LocalTime end = new LocalTime(18, 46);
LocalTime current = start;
for (int i = 0; current.isBefore(end); i++) {
// code your print action here
current = current.plusMinutes((i < 2) ? 30 : 60);
}
Then you get an action for following times:
13:46
14:16
14:46
15:46
16:46
17:46
I have orders that come in it at various times during the week and I have a set of rules for when we can and cannot accept orders. For example, we don't accept orders between 4:45pm and 5:15pm on Wednesday. So if an order came in at 3pm, everything is fine. If an order came in at 5pm we would need to reject it. These rules are based on the day of the week and change daily.
My question, is using joda time, what is the best way to check if the current time is in this time window?
I'm open to other technologies, however I'm currently using joda time through the scala tools time wrapper.
I'm currently working with something like this:
val now = DateTime.now
val wednesdayNoTradeInterval:Interval = ??
now.getDayOfWeek match {
case WEDNESDAY => wednesdayNoTradeInterval.contains(now)
}
You might try something like this:
implicit def dateTimeToLocalTime(dateTime: DateTime) = dateTime.toLocalTime
type Interval[T] = (T, T)
def during(interval: Interval[LocalTime])(time: LocalTime) = interval match {
case (start, end) => start < time && time < end
}
def day(day: Int)(time: DateTime) = time.dayOfWeek.get == day
val fourish = new LocalTime(16, 45)
val afternoon = during((fourish, (fourish + (30 minutes)) )) _
val wednesday = day(WEDNESDAY) _
val thursday = day(THURSDAY) _
def acceptingOrders = !{
val now = DateTime.now
wednesday(now) && afternoon(now)
thursday(now) && afternoon(now)
}
And use it like this:
acceptingOrders // ?
For each day of the week, store a list of pairs of LocalTime instances between which orders are rejected.
Then when an order is placed at a given DateTime, get the pairs associated with the dateTime's day of week, transform the DateTime into a LocalTime, and check if this LocalTime is contained between the start and end of at least one pair.
Check out the Span class in JChronic: https://github.com/samtingleff/jchronic/blob/master/src/main/java/com/mdimension/jchronic/utils/Span.java
It would be trivial to create something similar and do a !<> check on the time in millis.
I am looking for a java library that when given from and to date would return a list of dates in weeks,months,quarter or year which ever is most applicable. I have done this manually and i wanted to know if this is already implemented and tested as a part of a standard package.
Example
Given 1/1/2009 , 1/4/2009 it should give 1/1/2009,1/2/2009,1/3/2009,1/4/2009
Given 1/1/2009 , 1/14/2009 it should give 1/1/2009,1/7/2009,1/14/2009
hope you that is clear :)
The DateTime class provided by Joda Time has methods such as plusDays(int), plusWeeks(int), plusMonths(int) which should help.
Assuming you want to get all the dates between start and end in weeks (pseudocode):
DateTime start = // whatever
DateTime end = // whatever
List<DateTime> datesBetween = new ArrayList<DateTime>();
while (start <= end) {
datesBetween.add(start);
DateTime dateBetween = start.plusWeeks(1);
start = dateBetween;
}
Alternative to Jado is use standart java API
Calendar start = // whatever
Calendar end = // whatever
List<Calendar> datesBetween = new ArrayList<Calendar>();
while (start.compareTo(end) <= 0) {
datesBetween.add(start);
Calendar dateBetween = start.add(Calendar.DAY_OF_MONTH, 7);
start = dateBetween;
}
java.time
The Answer by Dónal using Joda-Time is correct, but outdated. The Joda-Time team has advised that we should migrate to the java.time framework built into Java 8 and later. Much of the java.time functionality has been back-ported to Java 6 & 7 and further adapted to Android.
LocalDate
For a date-only value, without time-of-day and without time zone, use the LocalDate class.
Half-Open
Generally the best practice in handling a span of time is known as Half-Open. In this approach, the beginning of the span is inclusive while the ending is exclusive. So with the example code below, you will see the results do not include the stop date. If you insist on the ending being inclusive, change the date.isBefore ( stop ) to ! date.isAfter ( stop ).
Example code
In its current state, the Question is vague, not addressing issues such as whether to consider if the start date happens to align with start of week or start of month and so on. Another issue: whether to use the Half-Open approach or not. So those issues are left as an exercise for the reader. ;-)
This code counts the number of days in the span of time. If under a week, we loop day-by-day. If over a week, we loop week-by-week. The same logic could be extended to handle month-by-month, quarter-by-quarter, and year-by-year as mentioned in the Question.
LocalDate start = LocalDate.of ( 2016 , Month.JANUARY , 2 );
LocalDate stop = start.plusDays ( 4 );
// LocalDate stop = start.plusWeeks ( 4 );
long days = ChronoUnit.DAYS.between ( start , stop );
List<LocalDate> dates = new ArrayList<> ();
if ( days == 0 ) {
dates.add ( start );// Just one date, as start equals stop.
} else if ( days < 7 ) { // Under a week, count day-by-day.
LocalDate date = start;
do {
dates.add ( date );
// Prep for next loop.
date = date.plusDays ( 1 );
} while ( date.isBefore ( stop ) ); // Using “isBefore” for Half-Open approach where ending is exclusive. For inclusive, use “! isAfter”.
} else if ( days > 7 ) { // Over a week, count week-by-week.
LocalDate date = start;
do {
dates.add ( date );
// Prep for next loop.
date = date.plusWeeks ( 1 );
} while ( date.isBefore ( stop ) ); // Using “isBefore” for Half-Open approach where ending is exclusive. For inclusive, use “! isAfter”.
} else {
// FIXME: ERROR. Should not be possible.
}
Dump to console.
System.out.println ( "start: " + start + " | stop: " + stop + " | dates: " + dates );
When run with the line for stop adding 4 days:
start: 2016-01-02 | stop: 2016-01-06 | dates: [2016-01-02, 2016-01-03, 2016-01-04, 2016-01-05]
When run with the line for stop adding 4 weeks:
start: 2016-01-02 | stop: 2016-01-30 | dates: [2016-01-02, 2016-01-09, 2016-01-16, 2016-01-23]
A sample java implementation using jodatime to create a date split over a large range, with minimal memory footprint.
https://github.com/atulsm/Test_Projects/blob/master/src/DateSplitter.java
I have fetched google maps ETAs (that is, durations) for some routes in the format of x hour(s) y min(s), and also if x > 24 then this format changes into u day(s) v hour(s).
Now I want to compare these values to some other ETAs so all I need to do is convert these format value into a minutes-only value.
Such as I have a value as 4 hours 34 mins, I want to change it into minutes using Java or such as 1 hour 1 min to minutes, there are records where hour indicated as 1 hour and 3 hours and same for mins and days.
Duration lessThanADay = Duration.ofHours(4).plusMinutes(34);
long minutes = lessThanADay.toMinutes();
This yields 274 minutes. The case for more than 24 hours is similar:
Duration moreThanADay = Duration.ofDays(1).plusHours(3);
This time toMinutes() returns 1620.
You can apply and mix plusHours() and plusMinutes()freely depending on which input numbers you’ve got.
EDIT: Your input strings are a bit more complicated. The Duration class can parse strings in ISO 8601 format, it goes like PT3H23M for a period of time of 3 hours 23 minutes. It may feel a little odd at first. However, we can fix your strings into this format:
private static Duration toDuration(String durationString) {
durationString = durationString.replaceAll(" days?", "D");
durationString = durationString.replaceAll(" hours?", "H");
durationString = durationString.replaceAll(" mins?", "M");
durationString = durationString.replace(" ", "");
if (durationString.contains("D")) {
durationString = durationString.replaceFirst("\\d+D", "P$0T");
} else {
durationString = "PT" + durationString;
}
return Duration.parse(durationString);
}
Let’s try this method on your example strings from the comment:
System.out.println(toDuration("3 hours 23 mins"));
System.out.println(toDuration("2 hours 56 mins"));
System.out.println(toDuration("1 hour 1 min"));
System.out.println(toDuration("1 day 18 hours"));
This prints:
PT3H23M
PT2H56M
PT1H1M
PT42H
So all of your strings have been recognized and parsed.
For the comparison, you don’t need to convert to minutes since Duration objects have a natural ordering and can be compared using compareTo, for example:
if (lessThanADay.compareTo(moreThanADay) < 0) {
System.out.println("Less");
}
(This prints Less.) You may find it more natural to compare the long minutes values using < and >, though.
You could split it on space...
String s[]="3 hours 23 mins".split(" ")
Then I'd just normalize everything to minutes
int minutes=0;
for(int i=0;i<=2;i+=2) {
if(s[i+1].startsWith("min"))
minutes+=s[i]
if(s[i+1].startsWith("hour"))
minutes+=s[i]*60
if(s[i+1].startsWith("day"))
minutes+=s[i]*60*24
}
If you were to put the lookup values into a map you could cut 2/3 from that loop, I'd do it that way in Groovy where the additional syntax would be minimal but in java it's a 50/50 if the added awkwardness loweres the redundancy enough to be worth it.