Regex HHmm validation- Java - java

I need to validate a textBox entry which contains time.
Time should be in HH:mm format and in 24-hour format.
For eg:
09:00, 21:00, 00:00, etc.,
Invalid entries:
2534, 090, *7&**, etc.,
If time entered is in HHmm format, then I need to append a ':'
to the entry.
For e.g:
If textBox entry= 0930, it should be changed to 09:30
This is what I have so far:
String textBoxVal = getTextBoxValue();
String colonCheck = ":";
if (!textBoxVal.contains(colonCheck)){
textBoxVal = textBoxVal.substring(0,2) + ":" + textBoxVal.substring(2,4);
}
But as is obvious, this code isn't going to work for all cases.
I'm not very familiar with regex, so any help on how this can be achieved using regex in Java, would be helpful!Thanks!

Solution using DateFormat, as pointed by Ranhiru
String theTime = "23:55";
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm"); //HH = 24h format
dateFormat.setLenient(false); //this will not enable 25:67 for example
try {
System.out.println(dateFormat.parse(theTime));
} catch (ParseException e) {
throw new RuntimeException("Invalid time "+theTime, e);
}

The following will do the trick for you
str = str.replaceAll("([01][0-9]|[2][0-3]):?([0-5]\d)", "$1:$2");
This will change 2300 to 23:00 and leave 23:00 as is.
You can also use (?:[01][0-9]|[2][0-3]):?[0-5]\d just for validation.
Just a further note - even though this one does the trick, if it is date validation that you want, then I would go the DateFormat route.

//Assuming text to match is in var mytext
var re=new RegExp(/^(\d\d):{0,1}(\d\d)$/);
var match=re.exec(mytext);
if (!match) alert("Bad value!");
else mytext=match[1]+':'+match[2];

Related

Java 8 DateTimeFormatterBuilder().appendOptional not working

My requirement is to validate that a date String is in the correct format based on a set of valid formats specified.
Valid formats:
MM/dd/yy
MM/dd/yyyy
I created a simple test method that uses the Java 8 DateTimeFormatterBuilder to create a flexible formatter that supports multiple optional formats. Here is the code:
public static void test() {
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))
.toFormatter();
String dateString = "10/30/2017";
try {
LocalDate.parse(dateString, formatter);
System.out.println(dateString + " has a valid date format");
} catch (Exception e) {
System.out.println(dateString + " has an invalid date format");
}
}
When I run this, here is the output
10/30/2017 has an invalid date format
As you see in the code, the valid date formats are MM/dd/yy and MM/dd/yyyy.
My expectation was that the date 10/30/2017 should be valid as it matches MM/dd/yyyy. However, 10/30/2017 is being reported as invalid.
What is going wrong ? Why is this not working ?
I also tried
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy[yy]"))
in place of
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))
but still had the same issue.
This code runs as expected if I use:
String dateString = "10/30/17";
in place of
String dateString = "10/30/2017";
I have 2 questions
What is going wrong here ? Why is it not working for "10/30/2017" ?
Using Java 8, how to correctly create a flexible Date formatter (a formatter that supports multiple optional formats) ? I know the use of [] to create optional sections in the pattern string itself. I'm looking for something more similar to what I am trying (avoiding [] inside the pattern string and using separate optional clauses for each separate format string)
The formatter does not work the way you expect, the optional part means
if there is nothing extra attached to the first pattern (e.g., "MM/dd/yy"), that is fine,
if there is something extra, it needs to match the second pattern (e.g, "MM/dd/yyyy")
To make it a bit clearer, try to run the sample code below to understand it better:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy"))
.toFormatter();
String[] dateStrings = {
"10/30/17", // valid
"10/30/2017", // invalid
"10/30/1710/30/2017", // valid
"10/30/201710/30/17" // invalid
};
for (String dateString : dateStrings) {
try {
LocalDate.parse(dateString, formatter);
System.out.println(dateString + " has a valid date format");
} catch (Exception e) {
System.err.println(dateString + " has an invalid date format");
}
}
==
10/30/17 has a valid date format
10/30/1710/30/2017 has a valid date format
10/30/2017 has an invalid date format
10/30/201710/30/17 has an invalid date format
==
This is only a simple solution, if performance is of your concern, the validation by catching the parsing exception should be the last resort
you may check the string by length or regex first before doing the date string parsing
you may also replace the stream with a method containing a simple for loop, etc.
String[] patterns = { "MM/dd/yy", "MM/dd/yyyy" };
Map<String, DateTimeFormatter> formatters = Stream.of(patterns).collect(Collectors.toMap(
pattern -> pattern,
pattern -> new DateTimeFormatterBuilder().appendOptional(DateTimeFormatter.ofPattern(pattern)).toFormatter()
));
String dateString = "10/30/17";
boolean valid = formatters.entrySet().stream().anyMatch(entry -> {
// relying on catching parsing exception will have serious expense on performance
// a simple check will already improve a lot
if (dateString.length() == entry.getKey().length()) {
try {
LocalDate.parse(dateString, entry.getValue());
return true;
}
catch (DateTimeParseException e) {
// ignore or log it
}
}
return false;
});
The builder's appendValueReduced() method was designed to handle this case.
When parsing a complete value for a field, the formatter will treat it as an absolute value.
When parsing an partial value for a field, the formatter will interpret it relative to a base that you specify. For example, if you want two-digit years to be interpreted as being between 1970 and 2069, you can specify 1970 as your base. Here's an illustration:
LocalDate century = LocalDate.ofEpochDay(0); /* Beginning Jan. 1, 1970 */
DateTimeFormatter f = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ofPattern("MM/dd/"))
.appendValueReduced(ChronoField.YEAR, 2, 4, century)
.toFormatter();
System.out.println(LocalDate.parse("10/30/2017", f)); /* 2017-10-30 */
System.out.println(LocalDate.parse("10/30/17", f)); /* 2017-10-30 */
System.out.println(LocalDate.parse("12/28/1969", f)); /* 1969-12-28 */
System.out.println(LocalDate.parse("12/28/69", f)); /* 2069-12-28 */

How to validate date(dd-mm-yyyy) without using regular expression in java? [duplicate]

I am using NetBeans IDE 7.2.
I have two separate classes newDateTest.java and newDateMethod.java, I am currently using my method class to validate a date from a user input which I have used in my test class.
So far in my test class I have the following:
try
{
Prompt ="please enter a date in the format dd-mm-yyyy";
System.out.println(Prompt);
String inputDate = in.next();
isValid = newDateMethod.validDate(input, input, input);
if (isValid){
System.out.println("VALID DATE");
} else {
System.out.println("INVALID DATE");
}
} catch (ArrayIndexOutOfBoundsException oob) {
System.out.println(oob);
}
However I have no idea how to validate the date in my method class as I am fairly new to Java.
Can anyone come to a solution? The sort of thing I've been taught to use is Date Formatter but I'm not sure whether this is appropriate here? If so, I wouldn't know how to use it
Like this:
Date date = null;
String inputDate = "07-01-2013";
try {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
formatter.setLenient(false);
date = formatter.parse(inputDate);
} catch (ParseException e) {
e.printStackTrace();
}
Updated on 13-Jul-2021:
I heartily agree with Ole V.V.'s comment below. All Java and Kotlin developers should prefer the java.time package.
I'll add a more modern example when time permits.
Have a look at SimpleDateFormat.parse(...) and do remember to surround with try-catch.
The standard JDK class for that is SimpleDateFormat:
DateFormat fmt = new SimpleDateFormat("yourformathere");
// use fmt.parse() to check for validity
Alternatively, I'd recommend using Joda Time's DateTimeFormat.
Rather than relying on exceptions which tend to have a small performance overhead, you can also use the DateValidator from the Apache commons routines package like this:
if (DateValidator.getInstance().validate(inputDate, "dd-MM-yyyy") != null) {
// Date is valid
}
else {
// Date is invalid
}
Small disclaimer though, I haven't looked at the implementation of the validate method and I'm not sure if it uses for instance the SimpleDateFormat...
java.time
I recommend that you use java.time, the modern Java date and time API, for your date work. It also gives you much preciser validation than the old SimpleDateFormat class used in some of the other answers.
String[] exampleInputStrings = { "07-01-2013", "07-01-017",
"07-01-2ooo", "32-01-2017", "7-1-2013", "07-01-2013 blabla" };
for (String inputDate : exampleInputStrings) {
try {
LocalDate date = LocalDate.parse(inputDate, DATE_FORMATTER);
System.out.println(inputDate + ": valid date: " + date );
} catch (DateTimeParseException dtpe) {
System.out.println(inputDate + ": invalid date: " + dtpe.getMessage());
}
}
Output from my example code is:
07-01-2013: valid date: 2013-01-07
07-01-017: invalid date: Text '07-01-017' could not be parsed at index 6
07-01-2ooo: invalid date: Text '07-01-2ooo' could not be parsed at index 6
32-01-2017: invalid date: Text '32-01-2017' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
7-1-2013: invalid date: Text '7-1-2013' could not be parsed at index 0
07-01-2013 blabla: invalid date: Text '07-01-2013 blabla' could not be parsed, unparsed text found at index 10
For a good validation you should probably add a range check. Use the isBefore and/or the isAfter method of LocalDate.
Also if you are going to do anything with the date more than validating it, you should keep the LocalDate from the parsing around in your program (not the string).
Link
Oracle tutorial: Date Time explaining how to use java.time.
You should use SimpleDateFormat.parse(String) method. if the passed date is of wrong format it throws an exception in which case you return false.
public boolean validateDate(String date) {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
try {
sdf.parse(date);
return true;
}
catch(ParseException ex) {
return false;
}
}
One can use joda-time.
DateTimeFormat.forPattern(INPUTED_DATE_FORMAT);
//one can also use it with locale
DateTimeFormat.forPattern(USER_DATE_FORMAT).withLocale(locale);
fmt.parseDateTime(INPUTED_DATE);
If parseDateTime throw IllegalArgumentException then date is not valid.

Date Validation in Jtextfield for the specified Format

I need to Validate Date in a specified format where both the inputs will be given only in the runtime in JTextfield and will be changing dynamically. Below is the code I have tried:
Date dd = new Date();
DateFormat df = new SimpleDateFormat(Date_format_text.getText());
try {
df.setLenient(false);
Date d1 = df.parse(Lower_date_text.getText());
System.out.println("Correct");
validator_LD.setVisible(false);
} catch (ParseException p) {
validator_LD.setText("*Not in mentioned Format '" + df.format(dd) + "'");
validator_LD.setVisible(true);
System.out.println("Wrong");
}
The above is.. i get the Date specified and the format specified from the text field and try to parse according to the specified format. If it doesn't match it will throw exception.
But this is not working properly in some cases :
If I give the Date 02/01/20'and the Format - dd/MM/YYYY where it should throw an exception since I have given the year as 20 and the format is 'YYYY' but i doesn't give exception.
Kindly help me.. Thanks in advance
First, you may want to take a look at How to Use the Focus Subsystem, paying attention to Validating Input which might help.
Second, as pointed out by #eatSleepCode, you're not actually parsing the text of the field, but are simply formatting an existing Date, so it will never throw an exception...
simple_format = new SimpleDateFormat(Date_format_text.getText());
// This is simply formatting the dates...
String ss = simple_format.format(dates);
Instead, you need to use something more like...
String test = "02/01/20";
String format = "dd/MM/yyyy";
SimpleDateFormat sdf = new SimpleDateFormat(format);
sdf.setLenient(false);
try {
Date date = sdf.parse(test);
if (!sdf.format(date).equals(test)) {
throw new ParseException(test + " is not a valid format for " + format, 0);
}
} catch (ParseException ex) {
ex.printStackTrace();
}
What this does, is test's the parser capabilities of the formatter, but also checks the input against what the resulting parsed Date would be formatted to, if these don't match it throws a ParseException. This is the closes I've been able to get to a strict parser...
Also, YYYY used to represent the week in year, not the year...

ignore any white space or new line in java date compare

I am trying to compare two dates in java. While the following code works fine, I would like to handle situations where there may be some alterations in the date format of the input dates.
For example, in the below code, the date format of the two dates are as yyyy/mm/dd hh:mm:ss am. But sometimes there are some additional white space/new line characters found in the input date and this causes exception.
java.text.ParseException: Unparseable date: "02/14/2013
07:00:00 AM"
The following is the code am trying to execute.
try
{
Date date1 = (Date)DATE_FORMAT_yyyy_mm_dd_hh_mm_ss.parse(slaTime); // usually the data comes as 2013/02/03 09:09:09 AM
Date date2 = (Date)DATE_FORMAT_yyyy_mm_dd_hh_mm_ss.parse(actualTime);// usually the data comes as 2013/02/03 09:06:09 AM
// a error occurs
if(date1.before(date2))
{
return "True";
}
else
{
return "False";
}
}
catch (ParseException e)
{
e.printStackTrace();
}
how to handle this?
One of the simplest solutions is to strip all whitespace from the String version of the date before you parse it. Alter your date format to not include any spaces (yyyy/MM/ddhh:mm:ssaaa), and use this to parse the stripped string.
final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/ddhh:mm:ssaaa");
final String dateStr = "02/14/2013 07:00:00" +
"\n AM";
Date failingDate = dateFormat.parse(dateStr);
Date passingDate = dateFormat.parse(dateStr.replaceAll("\\s",""));
For Month in year Use M instead of m
Correct date format would be yyyy/MM/dd hh:mm:ss aaa. And If there is any additional space or new line then you must remove it other wise it will failed to parse your string to date, your should exact match with format .
I would suggest you to remove all space and new line character then parse it.
you can use format like - yyyy/MM/ddhh:mm:ssaaa where there is no space. And replaceAll your space and new Line with empty String.
Date date = new SimpleDateFormat("yyyy/MM/ddhh:mm:ssaaa").parse("2013/02/1407:00:00AM");
and you actual code could be like -
dateString = dateString.replaceAll("\\s","");
SimpleDateFormat("yyyy/MM/ddhh:mm:ssaaa").parse(dateString);

Getting time from String

My Java code must get string "HH:MM" from console and needs to operate with it.
is there possible to parse such time from string in order to add, for example,2 hours.
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter some time:");
String enteredTime = in.readLine();
// here I want to get time in some variable
Thanks!
As result I have to get three dates and define is there three date between another dates .
I understand that I can split string on parts and work with their, but I'm lloking for simple way to operate with such times.
I found good solution:
SimpleDateFormat parser = new SimpleDateFormat("HH:mm");
Date ten = parser.parse("10:00");
Date eighteen = parser.parse("18:00");
try {
Date userDate = parser.parse(someOtherDate);
if (userDate.after(ten) && userDate.before(eighteen)) {
...
}
} catch (ParseException e) {
// Invalid date was entered
}
sdf = new java.text.SimpleDateFormat ("HH:mm");
sdf.parse ("13:47");
I understand you want to do some date arithmetics like adding durations to dates. Then you should definitely use joda time instead of java.util.Date and Calendar.
Joda gives you Period and Duration entities and a nice and readeable API.

Categories

Resources