While statement with Calendar.after doesn't start - java

So I've spend a fair amount of Googling and looking through things, but I just can't get it to work. It won't consider the statement as true, even though the request.getEnd() is a couple days after the current startCal.getTime. Any ideas?
while(startCal.after(request.getEnd()))
{
/* Calculate new beginning */
startCal.add(Calendar.DATE, 1);
newBegin = startCal.getTime();
System.out.println(newBegin);
/* Calculate new ending */
endCal.add(Calendar.DATE, 1);
newEnd = endCal.getTime();
/* Setting new dates and series ID */
localRequest.setBegin(newBegin);
localRequest.setEnd(newEnd);
localRequest.setSeriesID(seriesID);
/* Sending new reservation to database */
//reserve(localRequest);
System.out.println("RESERVATION DONE");
}

even though the request.getEnd() is a couple days after the current
startCal.getTime.
Then it makes sense that it wouldn't start! This line of code:
while(startCal.after(request.getEnd()))
Says "While start cal is after request end." You are describing your data as the opposite!

Calendar#after returns whether this Calendar represents a time after the time represented by the specified Object.
So, your code is currently checking whether startCal is after request.getEnd(), which from your description is the opposite of what you're trying to do.
It would make more sense to use Calendar#before here to get the desired result.

Related

How to obtain current TAI time?

How can I obtain the current TAI time in milliseconds in Linux using either Java or C++?
The reason I need this is to be able to accurately take timestamps over a long period of time (on the order of years) and still be able to compare them, without worrying about leap seconds. It is possible for multiple measurements to take place during a leap second and all measurements need to be unambiguous, monotonically increasing, and linearly increasing. This will be a dedicated Linux server. This is for a scientific project which needs precision of about .5 seconds.
I do not currently wish to invest in a GPS timekeeper and hope to use NTP to pool.ntp.org in order to keep the system clock on track.
I have looked into the following solutions:
Java 8 or the ThreeTen Project
The only way to obtain a TAIInstant is to use an Instant and then convert it which, according to the specs, "Conversion from an Instant will not be completely accurate near a leap second in accordance with UTC-SLS." That in and of itself is not a big deal (in fact, using UTC-SLS would also be acceptable). However, using now() in the Instant class also seems to just be a wrapper for System.currentTimeMillis(), which makes me think that during the leap second, the time will still be ambiguous and the project will not actually give me TAI time. The Java 8 specifications also state:
Implementations of the Java time-scale using the JSR-310 API are not
required to provide any clock that is sub-second accurate, or that
progresses monotonically or smoothly. Implementations are therefore
not required to actually perform the UTC-SLS slew or to otherwise be
aware of leap seconds.
Using a right/? timezone
This seems like it would work, however I am not sure if the implementation is smart enough to continue working during a leap second or if System.currentTimeMillis() would even give TAI time. In other words, would the underlying implementation still use UTC, thus giving an ambiguous time during the leap second which is then converted to TAI, or does using a right/ timezone actually work with TAI using System.currentTimeMillis() always (ie even during leap second)?
Using CLOCK_TAI
I tried using CLOCK_TAI in the Linux kernel but found it to be completely identical to CLOCK_REALTIME in my test:
Code:
#include <iostream>
#include <time.h>
long sec(int clock)
{
struct timespec gettime_now;
clock_gettime(clock, &gettime_now);
return gettime_now.tv_sec;
}
int main()
{
std::cout << sec(0) << std::endl; // CLOCK_REALTIME
std::cout << sec(1) << std::endl; // CLOCK_MONOTONIC
std::cout << sec(11) << std::endl; // CLOCK_TAI
return 0;
}
The output was simply:
1427744797
6896
1427744797
Using CLOCK_MONOTONIC
The problem with this is that the timestamps need to remain valid and comparable even if the computer restarts.
CLOCK_REALTIME and CLOCK_TAI return the same because the kernel parameter tai_offset is zero.
Check by using adjtimex(timex tmx) and read the value. I think that ntpd will set it if it is new enough (>4.2.6) and has a leap second file. It may also be able to get it from upstream servers but I haven't been able to verify. The call adjtimex() can set tai_offset manually when run as root. You will need a new-ish man page for adjtimex to see the parameters to set. My debian man page was too old but the command worked.
In addition to the correct accepted answer I would also mention the free Java library Time4J (min version v4.1) as possible solution because
I have written it to fill a gap in Java world (java.time cannot do all),
other answers given so far only talk about C++ (but you also asked for Java),
it works according to the same principles described by #user3427419.
It uses a monotonic clock based on System.nanoTime() but even allows custom implementations via the interface TickProvider. For the purpose of calibration, you can either use net.time4j.SystemClock.MONOTONIC, or you use an SNTP-clock named SntpConnector which just needs some simple configuration to connect to any NTP-time-server you want. And thanks to the built-in leap-second-table Time4J can even show you the announced leap second at the end of this month - in ISO-8601-notation or even as formatted local timestamp string in any timezone (using i18n-module).
A recalibration (in case of NTP - reconnect) of the clocks is possible meaning the clocks can be adapted to intermediate time adjustments (although I strongly recommend not to do it during your measurements or during a leap second). Although such a reconnect of an SNTP clock would normally cause the time stepping back in some cases Time4J tries to apply a smoothing algorithm (if activated in clock configuration) to ensure monotone behaviour. Detailed documentation is available online.
Example:
// Step 0: configure your clock
String ntpServer = "ptbtime1.ptb.de";
SntpConnector clock = new SntpConnector(ntpServer);
// Step 1: Timestamp start of the program and associate it with a counter
clock.connect();
// Step 2: Use the counter for sequential measurements at fixed intervals
Moment m = clock.currentTime();
System.out.println(m); // possible output = 2015-06-30T23:59:60,123456789Z
// Step 3: Timestamp new counter value(s) as necessary to keep your data adequately synced
clock.connect();
I doubt if any C++-based solution is more simple. More code demonstrations can also be studied on DZone.
Update (answer to question in comment):
A slightly simplified solution how to automatically download the given IETF-resource for new leap seconds and to translate it into a Time4J-specific format might look like this:
URL url = new URL("https://www.ietf.org/timezones/data/leap-seconds.list");
BufferedReader br =
new BufferedReader(
new InputStreamReader(url.openStream(), "US-ASCII"));
String line;
PlainDate expires = null;
Moment ntpEpoch = PlainTimestamp.of(1900, 1, 1, 0, 0).atUTC();
List<PlainDate> events = new ArrayList<PlainDate>();
try {
while ((line = br.readLine()) != null) {
if (line.startsWith("##")) {
long expraw = Long.parseLong(line.substring(2).trim());
expires = ntpEpoch.plus(
expraw, TimeUnit.SECONDS)
.toZonalTimestamp(ZonalOffset.UTC).toDate();
continue;
} else if (line.startsWith("#")) {
continue; // comment line
}
// this works for some foreseeable future
long epoch = Long.parseLong(line.substring(0, 10));
// this is no leap second
// but just the official introduction of modern UTC scale
if (epoch == 2272060800L) {
continue;
}
// -1 because we don't want to associate
// the leap second with the following day
PlainDate event =
ntpEpoch.plus(epoch - 1, TimeUnit.SECONDS)
.toZonalTimestamp(ZonalOffset.UTC).toDate();
events.add(event); // we don't assume any negative leap seconds here for simplicity
}
} finally {
br.close();
}
// now let's write the result into time4j-format
// use a location relative to class path of main program (see below)
String path = "C:/work/leapseconds.txt";
Writer writer = new FileWriter(new File(path));
String sep = System.getProperty("line.separator");
try {
for (PlainDate event : events) {
writer.write(event + ", +" + sep);
}
writer.write("#expires=" + expires + sep);
} finally {
writer.close();
}
System.out.println(
"Leap second file was successfully written from IETF-resource.");
// And finally, we can start the main program in a separate process
// with the system property "net.time4j.scale.leapseconds.path"
// set to our leapsecond file path (must be relative to class path)
Some notes:
I recommend to write this code as subprogram called by a simple batch program in order to avoid the main program being dependent on internet connectivity. This batch file would finally call the main program with the mentioned system property. If you set this property then the leap seconds will be read from the file specified there, and any eventually available tzdata-module would then stop to yield any concurrent leap second informations.
The reason I need this is to be able to accurately take timestamps
over a long period of time (on the order of years) and still be able
to compare them, without worrying about leap seconds. It is possible
for multiple measurements to take place during a leap second and all
measurements need to be unambiguous, monotonically increasing, and
linearly increasing.
Then your design is suboptimal. You cannot use time and then somehow meddle through leap seconds. This actually comes up often enough and people fall into the same trap of timestamping measurements using wall clock.
Timestamp start of the program and associate it with a counter
Use the counter for sequential measurements at fixed intervals
Timestamp new counter value(s) as necessary to keep your data adequately synced
If you avoid timestamping for the 1 second that leapsecond can occur (midnight!), you are home free because those can be adjusted later.
Now if you insist on using TAI without counter, all you need is a table with leap seconds that need to be accounted for. Then just use monotonic time. There is also libraries that can do this for you, but they may be out of date so you'll have to maintain them yourself,
http://skarnet.org/software/skalibs/libstddjb/tai.html
You have to implement a TAI clock based on C++ std::steady_clock or similar. To synchronize your TAI clock you could rely on GPS or NTP.
Option TAI from NTP: Your TAI implementation would need knowledge about leap seconds. Probably NTP protocol or referenced resources are the most reliable sources of current and future leap seconds.
Option TAI from GPS: GPS clock has a fixed offset to TAI, you do not have to mess with leap seconds

Logical Time Display in android

My android application needs to display time which has to be incremented according to a logical check
my condition example is below
d = (String) DateFormat.format("yyyy-MM-dd,hh:mm:ss", new java.util.Date());
if(condition)
{
//i want to increment the time for about an hour and display
}
else
{
// increment the date to 1 and display
}
am not concerned about the condition but on the code for incrementation of time and date
now how to code in order to increment accordingly to the above mentioned time format
Umm.
Use Calendar instead.
If you look at the documentation, you should be able to figure out how to do what you want.
If you can't figure it out from the docs (after putting forth honest effort), then I'll be happy to elaborate on the process.

Java: Date range check with open end date

What is most efficient way to compare date range in case of open end date i.e. optional end date? I want to compare effective date and optional end date given by user with any existing overlapping effective date and optional end date in database.If they overlap I want to display error message. Effective date is required and end date is optional.
Important:
effective and end date situation can be implemented in two general ways.
1) By having end date as DB column
For example, Mortgage or saving account rate. The rate becomes effective at certain point of time and then it stays in effect till next rate becomes effective and ends previous rate's effect.At given point of time at least one record will be in effect.
2) By not having end date in database
For example, Discount, coupoun, promotion or special offer. These all can become effective and end at certain point of time. It is possible that at given time no special offer or discount is running.
Scenario 1 is easy to implement. Every time you insert or edit the record you have to check there is no equivelent record in db with exact same effective date(and time).
Scenario 2 may have two further flavors.
2.1) End date is always required.(user entered or default with year 9999)
In such case, if you find any record that has (start1 <= end1 and start2 <= end2) then you have overlap.
2.2) End date is optional in that case null means positive infinity. User can enter end date or leave it blank.
This can be tricky to validate as more possible combination. You may need to generate query dynamically based on user has given end date or not
if(userEnd != null) {
query.append(dbStart<=userEnd)
}
query.append(dbEnd is null || dbStart>=userStart && dbEnd>=userStart)
If this query finds any result then you are overlaping range. Going one step further if you have requirement to automatically end date previous record if previous record's end date is null then you may want to modify above query as below to pass validation.
if(userEnd != null) {
query.append(dbStart<=userEnd)
}
query.append((dbEnd is null && dbStart>=userStart) || (dbStart>=userStart && dbEnd>=userStart))
Depending on other requirements you may need deleteDate to mark record invalid. Possible combination can be
Effective Date(Required) | Deleted Date (Optional)
OR
Effective Date(Required) | End Date(Required or Optional) | Deleted Date (Optional)
I made a schematic image about a reference interval, which might be open ended (gradient), and a timespan to compare:
The 5 basic cases a-e are without open end. Let's consider the timespan to compare not being open ended in the beginning.
Let's further define, that no two dates matches exactly - maybe because they are measured in microseconds. It doesn't really matter, because you will just switch from < to <= or not, whatever you consider to be a valid assumption.
From the basic cases, we see, they always overlap, except the sample.end is < reference.start or sample.start > ref.end.
Who would have thought it is that easy?
Well - let's see, what happens, if ref.end is open. Case a is not affected, but case e will overlap then too.
That was an easy one, wasn't it?
Now we get difficult: What, if the sample is open ended? Case a will now overlap, but e not being affected.
Hardcore experience: Both dates are open ended: Then an overlap occured.
Conclusion: If in doubt, do an image. Here it was inkscape.

Getting JODA Duration to work

The following code does not print the days correctly, I need to print out days and minutes as well.
Duration duration = new Duration(1328223198241L - 1326308781131L);
Period p2 = new Period(duration.getMillis());
System.out.println(p2.getDays()); // prints 0, should print 22 days
System.out.println(p2.getHours()); // prints 531 which is expected.
According to the javadoc, "Only precise fields in the period type will be used. For the standard period type this is the time fields only. Thus the year, month, week and day fields will not be populated." thus you are getting zero.
Consider this alternative.
Duration duration = new Duration(1328223198241L - 1326308781131L);
Period p2 = new Period(duration.getMillis());
System.out.println(p2.getHours()); // prints 531 which is expected.
System.out.println(p2.toStandardDays().getDays()); // prints 22 days
This behavior is explained in the javadocs: "duration is larger than one day then all the remaining duration will be stored in the largest available precise field, hours in this case."
If you explain what you're trying to do, as opposed to how you're trying to do it, then I'm sure we'll be able to help out. For example, to find what I think you're trying to get from p2.getDays():
Days.daysBetween(dateTime1, dateTime2).getDays()
Does the following not suffice: System.out.println(duration.getStandardDays());

Java Compare dates to check if in range

ok not as simple as title may make it sound. I tried this in a very primal way with c# and it worked, but I have a feeling a better job could be achieved with Java and Oracle as database. So the thing is:
I have a reservation system. multiple bookings could be made on the same day for period between date X and date Y as long as each day in the range can accommodate the requested number. Maximum number of clusters to reserve is 46. Hence logically you would look at each day as a holder of 46 cluster reservation and deduce from that.
Now what I have difficulty working out is:
when there are n number of bookings stored and valid in database, then I want to make new booking. So how do I check if this new date range falls within any of the previously booked days or not. Not talking simply here about x falling in y (as ranges). More like:
X_______________________________________Y
X________________________________y
X________________________________Y
X________________________________Y
as u can see the overlap is happening.
Please let me know how could I do this as it will affect early design of objects
Regards
Assume your date has two methods: isBefore(Date other) and isAfter(Date other). Obviously if they don't you can cure this with an external method or wrapping or something. Edit: java.util.Date has compareTo method you could use.
You do this:
public boolean overlapsWithExisting(Booking booking) {
final Date early = booking.getStart();
final Date late = booking.getEnd();
for(Booking existing : existingBookings) {
if(!(early.isAfter(existing.getEnd()) || late.isBefore(existing.getStart()))
return true;
}
return false;
}
We compare this booking to all existing bookings. If this booking ends before the existing booking even starts, or if this booking starts after the existing booking ends, then it doesn't conflict. Any other condition and they will overlap.
Do this to each booking.
Joda-Time – Interval
Rather than roll your own, use the Interval class in the Joda-Time library. An Interval is a pair of specific points along the timeline, each defined as a DateTime instance.
The Interval class offers overlap, gap, and abuts methods.
Half-Open
Those methods wisely use the Half-Open approach to spans of time where the beginning is inclusive while the ending is exclusive. Search StackOverflow for more info.

Categories