3

For example: 2013-08-11T17:22:04.51+01:00

In this stackoverflow answer cover ISODateTime without .51 part.

Please help to correct this regex

^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:Z|[+-][01]\d:[0-5]\d)$

to handle my format.

Toto
  • 89,455
  • 62
  • 89
  • 125
Bagrat
  • 65
  • 1
  • 6
  • 3
    [Why is “Can someone help me?” not an actual question?](https://meta.stackoverflow.com/q/284236/3788176) – Andy Turner May 10 '19 at 14:45
  • 2
    Why would you use regex for something like this when you can try parsing it as a `ZonedDateTime` instead? – Jacob G. May 10 '19 at 14:46
  • Thanks for suggestion @Jacob G, but I should validate the value of property with javax.validation. – Bagrat May 10 '19 at 15:02

3 Answers3

5

Using capturing groups, you can simply design an expression to capture anything that you wish from your input. For example this expression,

(\d{4}-\d{2}-\d{2})[A-Z]+(\d{2}:\d{2}:\d{2}).([0-9+-:]+)

divides your input into three capturing groups and you can simply call them using $1-$3.

You can also add any char that you may want to in [].

enter image description here

RegEx Descriptive Graph

This graph shows how the expression would work and you can visualize other expressions in this link:

enter image description here

Java Test

import java.util.regex.Matcher;
import java.util.regex.Pattern;

final String regex = "(\\d{4}-\\d{2}-\\d{2})[A-Z]+(\\d{2}:\\d{2}:\\d{2}).([0-9+-:]+)";
final String string = "2013-08-11T17:22:04.51+01:00";
final String subst = "\\1 \\2 \\3";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);

// The substituted value will be contained in the result variable
final String result = matcher.replaceAll(subst);

System.out.println("Substitution result: " + result);

JavaScript Demo

const regex = /(\d{4}-\d{2}-\d{2})[A-Z]+(\d{2}:\d{2}:\d{2}).([0-9+-:]+)/gm;
const str = `2013-08-11T17:22:04.51+01:00`;
const subst = `\nGroup 1: $1\nGroup 2: $2\nGroup 3: $3\n`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);

console.log('Substitution result: ', result);

Basic Performance Test

This JavaScript snippet shows the expression performance using a simple 1-million times for loop.

const repeat = 1000000;
const start = Date.now();

for (var i = repeat; i >= 0; i--) {
 const string = '2013-08-11T17:22:04.51+01:00';
 const regex = /(\d{4}-\d{2}-\d{2})[A-Z]+(\d{2}:\d{2}:\d{2}).([0-9+-:]+)/gm;
 var match = string.replace(regex, "\nGroup #1: $1 \n Group #2: $2 \n Group #3: $3 \n");
}

const end = Date.now() - start;
console.log("YAAAY! \"" + match + "\" is a match  ");
console.log(end / 1000 + " is the runtime of " + repeat + " times benchmark test.  ");
Emma
  • 27,428
  • 11
  • 44
  • 69
4

Regular expressions are convenient sometimes, but as a rule hard to read and (as you have experienced) hard to debug. Java has built-in parsing and validation of ISO 8601 format, and it accepts strings with and without decimals like .51. I understand that you are asking because you need to validate through javax.validation, which requires a regex. So only for other readers: the choice is obvious: don’t use regex here.

    try {
        OffsetDateTime.parse("2013-08-11T17:22:04.51+01:00");
        System.out.println("Valid ISO 8601");
    } catch (DateTimeParseException e) {
        System.out.println("Not valid ISO 8601");
    }

Valid ISO 8601

Caveat: OffsetDateTime.parse still doesn’t accept all variants of ISO 8601, but far more variants than your regular expression does.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

This regex should do the job:

^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$

ref. https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/

Bruno
  • 4,685
  • 7
  • 54
  • 105