I use this code to format a formatted text field to enter month & day:
SimpleDateFormat sdf = new SimpleDateFormat("MM.dd");
DateFormatter df = new DateFormatter(sdf);
DefaultFormatterFactory ddf = new DefaultFormatterFactory(df, df, df, df);
datumTextField.setValue(new Date(System.currentTimeMillis()));
datumTextField.setFormatterFactory(ddf);
When an invalid date is entered, eg. 13.10, a magican changes it to 1.10 after this line:
DateOfAdding = datumTextField.getText();
so the DateOfAddig value is 1.10.
How to turm the magican off?
tl;dr
MonthDay.parse(
"12.31" ,
DateTimeFormatter.ofPattern( "MM.dd" )
)
Catch DateTimeParseException for invalid input.
java.time.MonthDay
The modern approach uses the java.time classes rather than the troublesome legacy classes seen in the Question.
Among the java.time classes is MonthDay, just what you need.
I suggest collecting input as two different numbers.
MonthDay md = MonthDay.of( x , y ) ;
If you insist, you can collect input as a combined string and parse. If so I suggest you and your user use standard ISO 8601 format: --MM-DD.
MonthDay md = MonthDay.parse( "--12-31" ) ;
Or define a pattern using DateTimeFormatter.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM.dd" ) ;
MonthDay md = MonthDay.parse( input , f ) ;
Trap for DateTimeParseException to detect invalid inputs.
String input = "13.10" ; // Invalid input. Month must be 1-12.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM.dd" ) ;
MonthDay md = null ;
try
{
md = MonthDay.parse( input , f ) ;
} catch ( DateTimeParseException e ) {
// … handle error …
System.out.println( "Invalid input: " + input ) ;
}
See this code run live at IdeOne.com.
Invalid input: 13.10
e: java.time.format.DateTimeParseException: Text '13.10' could not be parsed: Unable to obtain MonthDay from TemporalAccessor: {MonthOfYear=13, DayOfMonth=10},ISO of type java.time.format.Parsed
md.toString(): null
You will want to call the SimpleDateFormat's setLenient method with false as a parameter so that the underlying Calendar used for parsing is set to non-lenient.
A non-lenient calendar will refuse field values that aren't in the expected range for this field, rather than accepting them and modifying other fields to make sense of them : in your case the month was rolled-over 12 and reached 1, while the year was increased by 1 and probably reached 1971 rather than the default-when-unspecified 1970.
From the Calendar's javadoc :
Leniency
Calendar has two modes for interpreting the calendar fields, lenient and non-lenient. When a Calendar is in lenient mode, it accepts a wider range of calendar field values than it produces. When a Calendar recomputes calendar field values for return by get(), all of the calendar fields are normalized. For example, a lenient GregorianCalendar interprets MONTH == JANUARY, DAY_OF_MONTH == 32 as February 1.
When a Calendar is in non-lenient mode, it throws an exception if there is any inconsistency in its calendar fields. For example, a GregorianCalendar always produces DAY_OF_MONTH values between 1 and the length of the month. A non-lenient GregorianCalendar throws an exception upon calculating its time or calendar field values if any out-of-range field value has been set.
Related
Im trying to do a connection with a database in Java using OOP and DAO pattern with MySQL and need to validate a date string in java and insert it into MySQl, the connection is fine the problem is the validation. I have to use Strings in both because thats what i was asked for but it doesnt recognize months like february or the ones with 30 days i tried with a while but apparentrly it can be done with the method im usinng (TemporalAccesor for unary operator ERROR). I also have to calculate the age of the person based on that date but since is a string, i cant figure out how to connect it with the date of the computer.
Thanks for any help, really need it
Method that throws the exception but allows Feb-31 or Sep-31:
I call it on the method where I fill all the other data and works well except for that detail
Also tried a regex but i saw is not convenient and doesnt catch that either
private static void FechaNacV(){
String date;
Scanner sc = new Scanner(System.in);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu/MM/dd");
date = sc.nextLine();
try {
formatter.parse(date);
System.out.println("Valid date");
} catch (Exception e) {
System.out.println("Invalid Date, try yyyy/mm/dd format again");
FechaNacV();
}
}
ResolverStyle.STRICT
The default resolver style in DateTimeFormatter will adjust your invalid 31st of February to the appropriate 28th or 29th.
If you want to avoid that tolerant adjustment, specify a different resolver style.
DateTimeFormatter
.ofPattern( "uuuu/MM/dd" )
.withResolverStyle( ResolverStyle.STRICT ) ; // Be strict: Reject 31st of February.
Call parse on the LocalDate class rather than the DateTimeFormatter class.
LocalDate ld = null ;
String input = "2022/02/31" ;
DateTimeFormatter formatter =
DateTimeFormatter
.ofPattern( "uuuu/MM/dd" )
.withResolverStyle( ResolverStyle.STRICT ) ; // Be strict: Reject 31st of February.
try {
ld = LocalDate.parse( input , formatter ) ;
} catch ( DateTimeParseException e ) {
System.out.println( e ) ;
}
System.out.println( ld ) ;
See this code run at Ideone.com.
java.time.format.DateTimeParseException: Text '2022/02/31' could not be parsed: Invalid date 'FEBRUARY 31'
null
I want to compare two date one is to take as current date and another one is static date that is from local variable. I want to compare date and month only i have written one program can anyone confirm is it right or not ?
String str="27/09";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM");
LocalDateTime now = LocalDateTime.now();
String date1=dtf.format(now);
System.out.println("fist date Date 1\t"+date1);
SimpleDateFormat sdformat = new SimpleDateFormat("dd/MM");
Date d1 = sdformat.parse(str);
String date2=sdformat.format(d1);
System.out.println("second date Date2 \t"+date2);
int result = date1.compareTo(date2);
if (result < 0) {
System.out.println("Date1 is before Date2");
}```
LOCALDATE>STATICVARIABLE DATE this is condition and want to compare date and month only.
tl;dr
MonthDay
.of( Month.OCTOBER , 1 )
.isAfter(
MonthDay
.parse(
"27/09" ,
DateTimeFormatter.ofPattern( "dd/MM" )
)
)
Run this code at Ideone.com.
true
java.time.MonthDay
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310.
For a day of month, use MonthDay class.
MonthDay md = MonthDay.of( 9 , 27 ) ;
For exchanging date-time values as text, ask the publisher of your data to use only standard ISO 8601 formats. For month-day, that format is --MM-DD.
String output = md.toString() ;
--09-27
If you must accept non-standard input, define a formatting pattern with DateTimeFormatter class.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM" ) ;
Parse your input.
String input = "27/09" ;
MonthDay sept27 = MonthDay.parse( input , f ) ;
sept27.toString(): --09-27
See this code run live at Ideone.com.
You can compare MonthDay objects by using their methods isBefore, equals, and isAfter.
If you want the current year-month, you need to a time zone. For any given moment, the date varies around the globe by time zone. So near the start/end of a month, it might be “next” month in Tokyo Japan while simultaneously “previous” month in Toledo Ohio US.
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
MonthDay currentYearMonth = MonthDay.now( z ) ;
I have a method taking Date field as a input parameter.
public static String formatDate(Date inputDate) {
// if user send the date with inputDate= new Date(00000000) or new Date(0L) because it is Java default date.
I have to send the exception error with message Invalid date.
}
What I did is something as below, But I am unable to get the error while passing the invalid date of zero count-from-epoch like "new Date( 0L )" as inputDate parameter.
public static String formatDate(Date inputDate) {
if (null == inputDate)
throw new FieldFormatException("Empty date field.");
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
return formatter.format(inputDate);
} catch (Exception ex) {
throw new FieldFormatException("Exception in formatting date field." + ex);
}
}
It sounds like you just want:
if (inputDate == null || inputDate.getTime() == 0L)
That will detect if inputDate is null or represents the Unix epoch.
As noted in the comments though:
Rejecting a single value is kinda dangerous - why is new Date(0) "wrong" but new Date(1) "right"?
This prevents you accepting legitimate input that happens to be the Unix epoch
The accepted Answer by Skeet is correct.
tl;dr
input.equals( Instant.EPOCH )
java.time
You are using troublesome old date-time classes that are now supplanted by the java.time classes.
The Instant class takes the place of Date as a moment on the timeline in UTC but with a finer resolution of nanoseconds rather than milliseconds.
You can convert when interfacing with legacy code not yet updated to java.time classes. To convert, call new methods added to the old classes.
Instant instant = myDate.toInstant() ;
Check for null.
if ( null == input ) {
throw new IllegalArgumentException( "Received invalid input: null." ) ;
}
Check for that count-from-epoch value zero that seems to be of special concern to you. The Instant class has a constant for that, for a count of zero nanoseconds from the epoch reference date-time used by Unix and Java: first moment of 1970 in UTC.
if ( input.equals( Instant.EPOCH ) ) {
throw new IllegalArgumentException( "Received invalid input: Instant.EPOCH. Input must be later than 1970-01-01T00:00:00Z." ) ;
}
You might want to check for recent date-time values, if required by your business rules.
if ( input.isBefore( Instant.now() ) ) {
throw new IllegalArgumentException( "Received invalid input. Input must not be in the past." ) ;
}
When generating a string take into account time zone. For any given moment, the date and the time-of-day vary around the globe by zone.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Your desired format happens to be the "basic" version of a standard ISO 8601 format. This format is predefined as a constant: DateTimeFormatter.BASIC_ISO_DATE.
String output = zdt.format( DateTimeFormatter.BASIC_ISO_DATE ) ;
I am reading an excel value that is it is of date which is of string type and i am converting it in date type to store the date in format of dd/MM/YYYY so below is the way i am doing it
private static final SimpleDateFormat outputDate = new SimpleDateFormat("dd/MM/yyyy");
String dealDateString = cell.getStringCellValue(); // inside this deal date is stored as 05/07/13
if (dealDateString != null) {
java.util.Date dealDate = convertStringToDate(dealDateString);
String dd = outputDate.format(dealDate); // ----> now the date is stored inside dd string as DD/MM/YYYY as 05/07/2013
DateFormat format = new SimpleDateFormat("dd/MM/yyyy", Locale.UK);
java.util.Date date = format.parse(dd); //--> but inside date object the year is stored as 13 that is year is stored as YY
}
below is the custom method i have designed that will take string and convert it into date object
public java.util.Date convertStringToDate(String stringValue) {
String[] formatStrings = { "dd/MM/yyyy", "dd-MMM-yyyy" ,"dd/MM/YY" , "dd-MM-YY"};
for (String formatString : formatStrings) {
try {
return new SimpleDateFormat(formatString).parse(stringValue);
} catch (ParseException e) {
logger.warn("##$$$$$### Error in invoice inside convertStringToDate method : ##$$$$$$#### "
+ ErrorUtility.getStackTraceForException(e));
}
}
return null;
}
now the date is converted into java date object but the year is deducted lets say if the year is 2014 then
year is stored as 14 , please advise how can i store the year as 2014 the main concern is that year is stored as two digits only i want to store it as YYYY
folks please advise
Try to write this line:
String[] formatStrings = { "dd/MM/yyyy", "dd-MMM-yyyy" ,"dd/MM/YY" , "dd-MM-YY"};
Like this:
String[] formatStrings = { "dd/MM/yyyy", "dd-MMM-yyyy" ,"dd/MM/yy" , "dd-MM-yy"};
The issue is the format.....
When you use "dd/MM/yyyy" as fomat, 05/07/13 is traeted as 05/07/0013 and not 05/07/2013 .
Reference from Java doc
For parsing with the abbreviated year pattern ("y" or "yy"), SimpleDateFormat must interpret the abbreviated year relative to some century. It does this by adjusting dates to be within 80 years before and 20 years after the time the SimpleDateFormat instance is created. For example, using a pattern of "MM/dd/yy" and a SimpleDateFormat instance created on Jan 1, 1997, the string "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64" would be interpreted as May 4, 1964. During parsing, only strings consisting of exactly two digits, as defined by Character.isDigit(char), will be parsed into the default century. Any other numeric string, such as a one digit string, a three or more digit string, or a two digit string that isn't all digits (for example, "-1"), is interpreted literally. So "01/02/3" or "01/02/003" are parsed, using the same pattern, as Jan 2, 3 AD. Likewise, "01/02/-3" is parsed as Jan 2, 4 BC.
Use
dd/MM/yy as format instead of dd/MM/yyyy.It will solve your issue.
String[] formatStrings = { "dd/MM/yy", "dd-MMM-yy" ,"dd/MM/yy" , "dd-MM-yy"};
Incorrect Parsing Pattern
The Answer by Abdelhak is correct: You are defining incorrect formatting pattern. The uppercase Y has a different meaning than lowercase y.
java.time
You are using the old date-time classes from the early years of Java. These classes have proven to be troublesome, flawed in design and implementation. Avoid them (java.util.Date/.Calendar & java.text.SimpleTextFormat).
Instead use the java.time framework built into Java 8 and later.
The java.time classes include LocalDate to represent a date-only value with no time-of-day.
// If used repeatedly many times, keep this List around for re-use rather instantiating over and over.
List<DateTimeFormatter> formatters = new ArrayList<>(4);
formatters.add( DateTimeFormatter.ofPattern("dd/MM/yy") );
formatters.add( DateTimeFormatter.ofPattern("dd-MM-yy") );
formatters.add( DateTimeFormatter.ofPattern("dd/MM/yyyy") );
formatters.add( DateTimeFormatter.ofPattern("dd-MM-yyyy") );
LocalDate localDate = null; // Using null as a flag for success/failure.
for( DateTimeFormatter formatter : formatters ) {
try {
localDate = LocalDate.parse( input , formatter );
} catch ( DateTimeParseException e ) {
// Ignore this exception, as we expect some.
}
}
if( null == localDate ) {
// … handle failure to parse. Must be unexpected input.
} else {
// … handle success. You now have a LocalDate object.
String output = localDate.toString(); // Generates a String in ISO 8601 format.
String outputInFormatNotRecommended = localDate.format( formatters.get( 0 ) );
}
If your goal is to serialize the date value as a String, I strongly suggest you use the standard ISO 8601 format (YYYY-MM-DD). This format is easily recognizable by most any culture, is easy to read, and sorts alphabetically as chronologically.
I have a date string in this format:
String fieldAsString = "11/26/2011 14:47:31";
I am trying to convert it to a Date type object in this format: "yyyy.MM.dd HH:mm:ss"
I tried using the following code:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
Date newFormat = sdf.parse(fieldAsString);
However, this throws an exception that it is an Unparsable date.
So I tried something like this:
Date date = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(fieldAsString);
String newFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").format(date)
However, this new format is now in the 'String' format but I want my function to return the new formatted date as a 'Date' object type. How would I do this?
Thanks!
You seem to be under the impression that a Date object has a format. It doesn't. It sounds like you just need this:
Date date = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(fieldAsString);
(You should consider specifying a locale and possibly a time zone, mind you.)
Then you've got your Date value. A format is only relevant when you later want to convert it to text... that's when you should specify the format. It's important to separate the value being represent (an instant in time, in this case) from a potential textual representation. It's like integers - there's no difference between these two values:
int x = 0x10;
int y = 16;
They're the same value, just represented differently in source code.
Additionally consider using Joda Time for all your date/time work - it's a much cleaner API than java.util.*.
The answer by Jon Skeet is correct and complete.
Internal to java.util.Date (and Date-Time seen below), the date-time value is stored as milliseconds since the Unix epoch. There is no String inside! When you need a textual representation of the date-time in a format readable by a human, either call toString or use a formatter object to create a String object. Likewise when parsing, the input string is thrown away, not stored inside the Date object (or DateTime object in Joda-Time).
Joda-Time
For fun, here is the (better) way to do this work with Joda-Time, as mentioned by Mr. Skeet.
One major difference is that while a java.util.Date class seems to have a time zone, it does not. A Joda-Time DateTime in contrast does truly know its own time zone.
String input = "11/26/2011 14:47:31";
// From text to date-time.
DateTimeZone timeZone = DateTimeZone.forID( "Pacific/Honolulu" ); // Time zone intended but unrecorded by the input string.
DateTimeFormatter formatterInput = DateTimeFormat.forPattern( "MM/dd/yyyy HH:mm:ss" ).withZone( timeZone );
// No words in the input, so no need for a specific Locale.
DateTime dateTime = formatterInput.parseDateTime( input );
// From date-time to text.
DateTimeFormatter formatterOutput_MontréalEnFrançais = DateTimeFormat.forStyle( "FS" ).withLocale( java.util.Locale.CANADA_FRENCH ).withZone( DateTimeZone.forID( "America/Montreal" ) );
String output = formatterOutput_MontréalEnFrançais.print( dateTime );
Dump to console…
System.out.println( "input: " + input );
System.out.println( "dateTime: " + dateTime );
System.out.println( "dateTime as milliseconds since Unix epoch: " + dateTime.getMillis() );
System.out.println( "dateTime in UTC: " + dateTime.withZone( DateTimeZone.UTC ) );
System.out.println( "output: " + output );
When run…
input: 11/26/2011 14:47:31
dateTime: 2011-11-26T14:47:31.000-10:00
dateTime as milliseconds since Unix epoch: 1322354851000
dateTime in UTC: 2011-11-27T00:47:31.000Z
output: samedi 26 novembre 2011 19:47
Search StackOverflow for "joda" to find many more examples.