I wonder if it's possible to parse any string (at least to try) to sql Date without specifing the string format? In other words I want to make a generic method who take as input a string and return an sql Date.
For instance I have:
String date1="31/12/2099";
String date2="31-12-2099";
and call parseToSqlDate(date1) and parseToSqlDate(date2) which will returns sql dates.
Short answer: No
Why: Parsing any string to a valid date is a task you as an intelligent being could not do (there is no "logical" way to determine the correct date), so you cannot "tell" a computer(program) to do that for you (see JGrice's comment, and there we still have 4-digit years).
Long answer: Maybe, if you are willed to either take risks or do not need a high rate of success.
How:
Define your minimal (format) requirements of a date. E.g. "a minimal date contains 1-8 numbers; 01/01/2001 , 01-01-01 , 01.01 (+current year) , 1.1 (+current year), 1 (+current month + current year) and/or "..contains 1-6 numbers and the letters for months"; 01-Jan-2001 and so on.
Split the input along any non-number/non-month-name characters, with a regex like [^0-9a-zA-Z] (quick thought, may hold some pitfalls)
You now have 1 to 3 (actually more if e.g. the time is included) separate numbers + 1 month name which can be aligned for year/month/day any way you like
For this "alignment", there are several possibilities:
Try a fixed format at first, if it "fits", take it, else try another (or fail)
(only of you get more than one entry at a time) guess the format by assuming all entries have the same (e.g. any number block containing values > 12 is not a month and > 31 is not a day)
BUT, and this is a big one, you can expect any such method to become a major PITA at some point, because you can never fully "trust" it to guess correctly (you can never be sure to have missed some special format or introduced some ambiguous interpretation). I outlined some cases/format, but definitely not all of them, so you will refine that method very often if you actually use it.
Appendix to your comment: "May be to add another parameter and in this way to know where goes day , month and so on?" So you are willed to add "pseudo-format-string" parameter specifying the order of day, month and year; that would make it a lot easier (as "simply" filtering out the delimiters can be achieved).
Related
I'm using the en_GB locale, but a similar issue may also affect other en_XX locales.
Under Java 15 the following code works:
LocalDate.parse("10-Sep-17", DateTimeFormatter.ofPattern("dd-MMM-yy", Locale.UK));
Under Java 16 it gives: DateTimeParseException: Text '10-Sep-17' could not be parsed at index 3
After spending a long time in the debugger I have traced this to this commit: 8251317: Support for CLDR version 38
This commit changes the abbreviated form of September in make/data/cldr/common/main/en_GB.xml from Sep to Sept for both the context-sensitive and standalone forms. None of the other months are touched, remaining as 3 characters.
I have verified that this is indeed a genuine change between CLDR versions 37 and 38, although I'm not sure when we Brits switched to using 4 letters for our 3-letter abbreviation for September...
Now this is annoying, as it has broken my datafile processing (although I suspect I can fix it by specifying Locale.ENGLISH rather than using the default locale in my code), but I can't decide if it counts as a bug that has been introduced that breaks my reliable 3-character-month match pattern, or whether this is actually meant to be a feature.
The JavaDoc says:
Text: The text style is determined based on the number of pattern letters used. Less than 4 pattern letters will use the short form. ...
and later:
Number/Text: If the count of pattern letters is 3 or greater, use the Text rules above. Otherwise use the Number rules above.
My bad for never having read this carefully enough to spot that textual values are handled differently to numbers, where the number of letters in your pattern sets the width. But this leaves me wondering how you are supposed to specify a fixed number of characters when you output a month, and equally why it can't be permissive and accept the three-character form when parsing rather than throw an exception?
At the end of the day this still feels like a regression to me. My code that has worked reliably for years parsing dates with 3-character months in now, with no warning, fails on all dates in September. Am I wrong to think this feels incorrect?
I am currently making an assignment for Java but I am stuck. I have to make a birthdate from the three parameters: day, month and year, which are numbers = int. With this I have to put in some checks for valid dates. That part I think is done, but I get stuck at the following:
I want an if statement to check the day, and if the day is correct, this block of code should be run trough
if (dag >=1 && dag <=31)
{
datum = dag;
}
datum Is a String, because I want to get the date like this: DD-MM-YYY
And dag is an Int. So whenever I try to compile this, BlueJ gives an error at this part saying "incompatible types". I assume this is because I try to place a Int in a String. Is this possible in any way, because I can't find out how.
Use String.valueOf method to convert int to string: -
int i = 32;
String str = String.valueOf(i);
And of course follow the advice in #Brian's answer as to what you should rather do in your case.
Don't make it a string. it's not. I think you should
create a Date object to represent your date (day/month/year combined)
use SimpleDateFormat to print that date out in the appropriate format
That's the proper OO way to do it. Otherwise you end up with a bunch of disparate disconnected variables representing in their combination some object type, but you can't manipulate them atomically, invoke methods on them etc. Holding everything as strings is known as stringly-typing (as opposed to strongly-typing) and is a particularly bad code smell!
At some stage check out Joda-Time for a better date/time API than those suggested above. However for the moment I suspect you've got enough on your plate without downloading extra jars.
I want to convert a String into Timestamp, the pattern for which is unknown. Is there any API given by java which allows us to feed in the string and returns the possible patterns that could work with it? I understand that one could have some pre-defined patterns against which the String can be parsed and checked. But, since this is a timestamp, the number combinations of different dates and times will be quite a lot. So, was looking for an efficient way of figuring out the pattern of the String-Timestamp.
Never heard about ready-to-use library for something like this, as #Eugene noted, possible combinations for all the patterns is huge so there is probably no such a library.
I would recommend rethinking your architecture.
If you just want to play with something like this you can create your own implementation.
Lets say that you parse the input and then you figure out the array of integers
(09, 21, 12, 0, 44, 33)
, you can assume that the array contains year, day, month, minute, hour and seconds (not sure if you can assume that - its just an example)
Once you have that array you can create all possible permutations of this array - example here
Then you can create a Date object for each combination:
DateTime dt = new DateTime(09, 12, 21, 0, 44, 33, 0);
(above example is for JodaTime)
If you know for example that the year value will always be sent with 4 characters then possible number of combinations will decrease of course, further you can assume that '26' will not be the value for the month etc.. you probably get the idea.
In this case , first I would switch to Joda Time : http://joda-time.sourceforge.net/
Then I would generate some (try to decrease the possibilities as much as you can, as there are way too many) the Patterns and try the date over them. If it does not throw an error (aka it fits, put it in an array), then return the array. This is probably a very non-optimized solution, but this is where I would start.
I really do not think that there are libraries for that. Also, you might want to explain why you want to do that. may be the solution is a bit simpler.
Cheers,
Eugene.
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.
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.