How do I create a DateFormat with an optional time argument? - java

I wish to construct a date format that will optionally have a time argument.
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd [hh:mm]");
Is it also possible to construct a date format object that is capable of parsing different formats? Such as try the current locale but then fall back to ISO-8601 or should I just write multiple date formats if one fails?
UPDATE: Looking back at this question I can see I didn't specify that the reason for multiple date formats was for parsing strings, not for formatting a date, thus ambiguity for formatting date objects wasn't a concern for me. If you take this into account the time portion is or is not included in the parsing string.

SimpleDateFormat won't let you do that. It doesn't support alternatives within a (single) format.
Even if it did, there would a problem. Consider using this
new SimpleDateFormat("yyyy-MM-dd [hh:mm]");
versus using
new SimpleDateFormat("yyyy-MM-dd hh:mm");
new SimpleDateFormat("yyyy-MM-dd ");
In the first case, when I parsed a date against the format, I couldn't tell the difference between "2010-01-01" and "2010-01-01 00:00" by looking at the Date delivered to me. In the 2nd case, I can.
In the first case, when I format a Date with zero in the minutes and seconds fields, it is not clear whether the result should end with "00:00" ... or not. In the second case, this is entirely in the hands of the application.
I guess that what I'm really doing here is raising the issue that dates and date/times mean different things to different people and in different contexts. Sometimes they mean instants and sometimes intervals. Sometimes a lack of expressed precision means imprecision, and sometimes that the precision is implied.
As developers we have to run the line between writing software that is annoyingly picky, and software that makes incorrect assumptions about what the user actually means by a date / time value. The first step in getting it right for the user is understanding the complexity of the problem. Overloading variations into a single format string is (would be) sweeping the problem under the carpet.

Related

Create calendar from String date without knowing format

I want to create an instance of Calendar with string date coming from server. Now I don't know what format server is sending .
It can be changed for different countries. I know I can ask them to add another key for dateFormat and create Calendar from it. But still I want to know Is there any way to create Calendar Instance without knowing current string date format.
I have gone through this and this. But none fulfill my requirement
This is impossible.
If the server sends the value "1/2/2017", you have no way of knowing if this refers to January 2nd or February 1st.
If the server sends the value "מָחָר", in theory you could realize that this might be a Hebrew translation of the word "tomorrow" (at least, according to Google Translate), but even then, it is not clear whether this is to be taken relative to today or some other date.
If the server sends the value "I want to create an instance of Calendar with string date coming from server", you have no means of creating a date from that, at least using any algorithm that would make sense to people.
And so on.
The only reason a server should return a date in an arbitrary format is if the date would only ever be read by the user who provided the value in the first place and presented as plain text verbatim, without parsing. Otherwise, the server should supply the date in a standardized format, with the UI consuming that date being responsible for formatting it in a user-friendly (and, ideally, locale-aware) fashion.
You're welcome to try to brute-force the problem, iterating over a series of date formats and seeing if any result in a seemingly-valid date. This fails the 1/2/2017 scenario (as there are at least two formats that would return a seemingly-valid date), but perhaps you know enough about the server to narrow down the possible formats to reduce the odds of collisions like this.
The Joda Date & Time API has a date parser which can parse date strings in many formats. Note that some datetime strings can be ambiguous: 10-09-2003 could mean October 9 or September 10.

Java, date from string without pattern

I need to get a Date instance from input file. I don't know the date format, but I want to get it from user profile settings.
Te following code does not working:
DateFormat form = DateFormat.getDa​teInstance(DateF​ormat.SHORT, Locale.getDefaul​t());
try {
Date t = form.parse("6/6/2015");
}
unparseable date error
I want to know if there is any way to get date from string without knowing the date string pattern.
I need this date to create MySQL query. Maybe there is another way to build this query without parsing date? I am using Entity Beans.
No. Consider the date "1/2/2015": is that February 1st or January 2nd. Depends on your locale.
Instead, you should be more specific: rather than getting a date formatter for your locale, use SimpleDateFormat with an explicit pattern.
I want to know if there is any way to get data from string without knowing the data string pattern.
Without any more information, this is very error prone. For example, consider "7/6/2015" - does that mean June 7th, or July 6th?
If you know the user's locale, you can do a lot better - for example, you could obtain DateFormat instances for long, medium, short and full date patterns for that locale, and try them one at a time. Bear in mind, however, that depending on where this code is executing, the default locale (as you're using at the moment) may not be the user's locale. You mention the user profile settings - hopefully that already contains a locale.
One alternative is to ask the user to tell you what the format is - maybe provide lots of different examples, and let them pick the one that matches.
Finally, if the file has lots of dates in and you're confident they'll all be in the same format, you could try to parse all of them in each of several different formats - that's likely to reduce the chances of error, as "7/6/2015" becomes unambigious if you've also seen "13/1/2015" for example.

Full date Validation in Java

I would like to make a validation for date. the date has many formats:
European and American styles. Also, number, shortcut or even the month full name.
I used Date.parse() but it's not accurate and it has many issues. For example: it doesn't pay attention to the leap year. Also, I added "35/02/2008" without giving me any exception.
I tried regular expression but all of what I found has an issue.
None of them cover the whole possibilities.
Please advise!
You should have a look at the Joda Time library: http://www.joda.org/joda-time/userguide.html#Input_and_Output
For example, you can create a DateTimeFormatter, and parse some text using it:
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMdd");
DateTime dt = fmt.parseDateTime(strInputDateTime);
The library allows for constructing complex date time patterns and it has knowledge of leap years etc.
Date validation does not make sense unless you are validating against a specific date format, or (carefully chosen) set of formats. To illustrate, consider this:
23/11/77
Is that a valid date? It depends!
If you are validating against "dd/MM/YY", then yes it is valid.
If you are validating against "MM/dd/YY", then no it isn't.
If you are validating against "dd/MM/YYYY", then it is valid but it doesn't mean what you think it means.
In short validating "any date" irrespective of format make no sense. The above date could be either valid or invalid, and can mean different things.
The fact that people "know" what these dates mean is worrying. In fact, when most people see a date, they interpret according to their own cultural norms ... without realizing that most dates are ambiguous if the format is not specified / agreed.
If you don't want (or aren't allowed) to use third-party libraries and prefer having manual control over validations, split the string using "/" as separators, then making conditions for all needed cases:
String pattern = "yyyy/MM/dd";
DateFormat df = new SimpleDateFormat(pattern);
String strDate = df.format(date);
String[] arrDate = strDate.split("/");
int year = Integer.parseInt(arrDate[0]);
int month = Integer.parseInt(arrDate[1]);
int day = Integer.parseInt(arrDate[2]);
if (month == 2 && day > 28) {
System.out.println("February has 28 days!");
}
// etc ...
If you are using java 8 then you dont need joda. There is an in-build API LocalDateTime similarly for UTC also there is an API.
The issue that the input may come with different format as soon as my app is an analysis tool.
If I wanna do it manually by splitting the date, I have to create a full class in order to check all the possibilities in all different formats.
There's no full regular expression for this issue. How come?

Best way to store time in java, in format of HH:MM

After doing my research I wasn't able to find a method or data type that should be used for variable in order to store time in format of HH:MM, I did find methods to get this from a string like "14:15:10", but I think this is not the best way, as I'll need to add or subtract from time. I tried doing this as a double, but ran into following issue, when you have a time like 05.45 stored and add 0.15 (or 15 minutes) to it, the result is 05.60 where as with HH:MM format you'd expect it to be 06.00.
I'm looked through java documentation and still am, but can't seem to find any way to achieve this, closest I got to is date format like dd/mm/yyyy hh:mm:ss
Use Joda Time. It provides much better operations to do date/time manipulation than standard java dates. If you want to use internal JDK classes, use java.util.Date.
Since Java 8, you can use the new API for dates and times, including Instant, ZonedDateTime and LocalDateTime. This removes the use for the third party library Joda time. It also makes calculations more easy and correct. The advice below is a bit dated but still has some good points.
—————
What you definitely should NOT do is store them in your own custom format. Store the Long value that represents the Unix Epoch.
A DateTime is nothing more than a number to a computer. This number represents the amount of seconds (or milliseconds) since 1970-01-01 00:00:00 UTC. It's beyond the scope of this answer to explain why this date was universally chosen but you can find this by searching for Unix Epoch or reading http://en.wikipedia.org/wiki/Unix_time.
This also means there is NO timezone information stored in a DateTime itself. It is important to keep this in mind when reasoning about dates and times. For things such as comparing DateTime objects, nothing concerning localization or timezones is done. Only when formatting time, which means as much as making it readable to humans, or for operations such as getting the beginning of the day, timezones come into play.
This is also why you shouldn't store the time like 20:11:15 in a string-like format because this information is meaningless without timezone information. I will give you 1 example here: Consider the moment when the clock is moved back 1 hour, such as when moving away from daylight savings time. It just happened in a lot of countries. What does your string 02:30 represent? The first or the second one?
Calculations such as subtraction are as easy as doing the same with numbers. For example: Date newDate = new Date(date1.getTime() - date2.getTime());. Or want to add an hour to a date? Date newDate = new Date(oldDate.getTime() + 1000 * 60 * 60);
If you need more complex stuff then using Joda time would be a good idea, as was already suggested. But it's perfectly possible to just do even that with the native libraries too.
If there's one resource that taught me a lot about date/time, it would be http://www.odi.ch/prog/design/datetime.php
Java has java.sql.Time format to work with time-of-day values. Just import it and create variables.
import java.sql.Time;
//now we can make time variables
Time myTime;
Just saw it on https://db.apache.org/derby/docs/10.4/ref/rrefsqlj21908.html
The answer that is right for your case depends on what you want to do.
Are you using a RDBMS as your persistence engine?
If so, are you already working with legacy data formats or are you building a database from the ground up?
Are you simply storing this data, or will you be doing extensive date arithmetic and/or precedence calculations?
Are you in one time zone or do you need to work with time instants across many time zones?
All of these things are important and factor into your decision of how to represent your times and dates.
If your needs require a lot of date arithmetic (eg. determining days between dates) or sorting based on timestamps, then consider using a floating point date format. The advantage of using a numeric format for timestamps is that doing date arithmetic and comparison/sorting operations becomes trivial; you merely do simple arithmetic. Another advantage is that floats and longs are primitive data types. They do not need to be serialized, they are already extremely lightweight, and everything you need to use them requires no external dependencies.
The main disadvantage to using numeric formats for timestamps is that they are not human friendly. You'll need to convert them to and from a String format to allow users to interact. Oftentimes, this is worth the effort. See: How do I use Julian Day Numbers with the Java Calendar API?
I recommend that you consider storing timestamps as Julian Day Numbers (JDNs) or Modified Julian Day Numbers (MJDs). Both will represent dates and times to millisecond precision using an 8 byte float. Algorithms for converting to and from display formats for both of these are highly standardized. They confer all the advantages of using numeric dates. Moreover, they are defined only for GMT/UTC which means that your timestamps are already universalizable across time zones right out of the box (as long as you localize properly).
If you dont want the full date object, your best bet is to store it in a string, but I personally would still recommend date as it also contains a lot of convenient methods that will come in handy. You can just get the time as a whole from a date object and ignore the rest.
In terms of "storing" a date, you should use a long. This is how the system sees it and how all calculations are performed. Yes, as some point out you will eventually need to create a String so a human can read it, but where people run into trouble is when they start thinking of a date in terms of format. Format is for readability, not for calculations. java.util.Date and java.util.Calendar are fraught with issues (Effective Java, Bloch, et. al. has plenty to say about it) but are still the norm if you need handy date operations.

How to parse four digit year only (with Joda Time)?

Is there a way to force Joda time to parse dates only when they contain four digit years? For example:
2009-11-11 - should parse
09-11-11 - should not parse
Tried the following code:
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
DateTimeFormatter formatter = builder.appendYear(4, 4).appendLiteral('-').appendMonthOfYear(1).appendLiteral('-').appendDayOfMonth(1).toFormatter();
formatter.parseDateTime("09-11-11");
Parses into 0009-11-11. Apparently minDigits in the method appendYear are only used for formatting when printing out the date.
The result is the same if I use appendYearOfEra(). If I use appendYearOfCentury(), it parses the year into 1909 instead.
We are implementing a general data parser, which will recognize various types of inputs. Also the example is a shortened form of the real deal (for simplicity). Real life scenarios parses dates which can have weekdays, months as words, time, zone and different characters separating month, day and year. Therefore, writing a RegEx or checking the content/length of the string can prove rather difficult.
Some real examples could look like this:
2009-11-11
Wednesday 2009-11-11T15:00:00
2009/11/11 15:00
and many more...
DateTimeFormatterBuilder#appendFixedDecimal() may well do what you need.
Alternatively, you could implement the DateTimeParser interface to create whatever parser you want and pass that into the DateTimeFormatterBuilder.
You can check the length of the date string.
You can build extremely specific parsers and formatters using DateTimeFormatterBuilder. There's generally no need to use this class directly, since most common formats are more easily available elsewhere in the API, but this is the builder class they all use under the covers.
What do you want to get from a user who enters '0001-01-01' as the date (that is, they entered 4 digits for the year, but the first three were zeroes)? What about '0999-12-31'? And '999-12-31'? And what about '10000-01-01' - the infamous Y10K1 problem?
If that is a legitimate value, then you are stuck with discovering the length of what the user typed as the year portion of the date (probably after any other parsing has been done), and making sure it is at least (or is it exactly?) four digits.
If that is not a legitimate value, then you are stuck with checking the year value after the date is parsed.
Or you can take the code and modify it so it includes your preferred definition of valid year.
1 I do not plan to start working on fixing the Y10K problem before 5000-01-02.

Categories

Resources