0

I have consecutive characters as date like 20210215 and 14032020 I am trying to convert to date string like 2021.02.15 and 14.03.2020

My first problem is the consecutive characters it is in 2 format type. Like:

1) 20210215
2) 14032020

And my second problem to convert them to date string without changing the format. Like:

1) 2021.02.15
2) 14.03.2020

When I search about regex couldn't find any pattern to convert the above {20210215} consecutive characters examples to date {2021.02.15} string.

What is correct regex pattern to convert both format as I describe above in Dart?

UPDATE-1:

I need to turn this string "20210215" to this "2021.02.15" as a string and not DateTime. Also I need to turn this string "14032020" to this string "14.03.2020". And I don't want to turn to DateTime string.

First I need to detected if the year is in beginning of the string or end of it. Than put dot (.) between the day, month and year string.

UPDATE-2: this is best I can found but it turns 02 day or month to 2. But I need as it is.

  var timestampString = '13022020';//'20200213';

  var re1 = RegExp(
    r'^'
    r'(?<year>\d{4})'
    r'(?<month>\d{2})'
    r'(?<day>\d{2})'
    r'$',
  );

  var re2 = RegExp(
    r'^'
    r'(?<day>\d{2})'
    r'(?<month>\d{2})'
    r'(?<year>\d{4})'
    r'$',
  );

  var dateTime;
  var match1 = re1.firstMatch(timestampString);
  if (match1 == null) {
    var match2 = re2.firstMatch(timestampString);
    if (match2 == null) {
      //throw FormatException('Unrecognized timestamp format');
      dateTime = '00.00.0000';
      print('DATE_TIME: $dateTime');
    } else {
      var _day = int.parse(match2.namedGroup('day'));
      var _month = int.parse(match2.namedGroup('month'));
      var _year = int.parse(match2.namedGroup('year'));
      dateTime = '$_day.$_month.$_year';
      print('DATE_TIME(match2): $dateTime');
    }
  } else {
    var _year = int.parse(match1.namedGroup('year'));
    var _month = int.parse(match1.namedGroup('month'));
    var _day = int.parse(match1.namedGroup('day'));
    dateTime = '$_year.$_month.$_day';
    print('DATE_TIME(match1): $dateTime');
  }

Output:

DATE_TIME: 2020.2.13

But I need to get output as 2020.02.13.

Second is match1 also prints 1302.20.20 But if I remove var match2 section and if format is like 20200213 it works but doesn't print the 0 as I post it above.

NTMS
  • 816
  • 7
  • 22
  • Are your years limited? I mean, can one of the strings have 1200 or 1912 or are they all 2020 and 2021? – Omar Si Mar 03 '21 at 17:55
  • Please check the link at the top. If you still have issues, please edit the question with the exact code you tried and state the current problem, and then let know via a comment. – Wiktor Stribiżew Mar 03 '21 at 18:00
  • If it's a fixed format like "DDMMYYYY", then a regex pattern using groups is simple. If it's not a fixed format, then it's much more complicated since there's no inherent way to tell what format an arbitrary string of 8 numbers can be. – Abion47 Mar 03 '21 at 19:46
  • @OmarSi years is not exactly as limited but start is like year 1900 and end is ... 2021, 2021, etc. – NTMS Mar 04 '21 at 06:32
  • @Abion47 incoming text format are: DDMMYYYY and YYYYMMDD type. – NTMS Mar 04 '21 at 06:34
  • @WiktorStribiżew I check the link. But it doesn't output as what I wanted. It outputs DateTime string. I need to turn this string "20210215" to this "2021.02.15" as a string and not DateTime. Also I need to turn this string "14032020" to this string "14.03.2020". – NTMS Mar 04 '21 at 06:47
  • I update my question post. – NTMS Mar 04 '21 at 06:50
  • Try `text.replaceAllMapped(RegExp(r'\b(?:((?:19|20)\d{2})(\d{2})(\d{2})|(\d{2})(\d{2})((?:19|20)\d{2}))\b'), (Match m) => m[4] == null ? "${m[1]}.${m[2]}.${m[3]}" : "${m[4]}.${m[5]}.${m[6]}")` – Wiktor Stribiżew Mar 04 '21 at 11:08
  • I will tru this afternoon thanks Wiktor. – NTMS Mar 04 '21 at 11:14
  • I just am guessing you want to only match years in the 20th and 21st centuries, and that means a single regex can handle that re-formatting. Also, I assume the dates can occur anywhere inside the text, but not glued to letters, digits and underscores. – Wiktor Stribiżew Mar 04 '21 at 11:22
  • @WiktorStribiżew thank you. It works. But how can make "''20151999''" so it can print as 20.15.1999? Because currently it prints 2015.19.99. where 19 as month and 99 as a day. – NTMS Mar 04 '21 at 14:39
  • Sorry, I do not get the requirements. I thought you only wanted to format dates. `20.15.1999` is not a valid date. – Wiktor Stribiżew Mar 04 '21 at 14:50
  • @WiktorStribiżew. the incoming string is '20121999' which means 20.12.1999 but it prints as 2012.19.99. which is not a valid date. So I guess after I replace I need to use another regex to check validity of the new string. But how can I check if 2012.19.99. is valid date? – NTMS Mar 04 '21 at 14:54
  • Ok, `text.replaceAllMapped(RegExp(r'\b(?:((?:19|20)\d{2})(0?[1-9]|1[0-2])(0?[1-9]|[12][0-9]|3[01])|(0?[1-9]|[12][0-9]|3[01])(0?[1-9]|1[0-2])((?:19|20)\d{2}))\b'), (Match m) => m[4] == null ? "${m[1]}.${m[2]}.${m[3]}" : "${m[4]}.${m[5]}.${m[6]}")`? – Wiktor Stribiżew Mar 04 '21 at 14:57
  • @WiktorStribiżew thanks its working. '20121999' becomes 20.12.1999 and if use '201519999' it prints without dot. So I will check string if contains a . means valid date. Thank you. – NTMS Mar 04 '21 at 15:04
  • How do you check if `120551205` is `12-05-1205` or `1205-12-05`? – Abion47 Mar 04 '21 at 15:45

1 Answers1

1

You can use

text.replaceAllMapped(RegExp(r'\b(?:((?:19|20)\d{2})(0?[1-9]|1[0-2])(0?[1-9]|[12][0-9]|3[01])|(0?[1-9]|[12][0-9]|3[01])(0?[1-9]|1[0-2])((?:19|20)\d{2}))\b'), (Match m) => m[4] == null ? "${m[1]}.${m[2]}.${m[3]}" : "${m[4]}.${m[5]}.${m[6]}")

The \b(?:((?:19|20)\d{2})(0?[1-9]|1[0-2])(0?[1-9]|[12][0-9]|3[01])|(0?[1-9]|[12][0-9]|3[01])(0?[1-9]|1[0-2])((?:19|20)\d{2}))\b regex matches

  • \b - a word boundary
  • (?: - start of a non-capturing group:
    • ((?:19|20)\d{2}) - year from 20th and 21st centuries
    • (0?[1-9]|1[0-2]) - month
    • (0?[1-9]|[12][0-9]|3[01]) - day
  • | - or
    • (0?[1-9]|[12][0-9]|3[01]) - day
    • (0?[1-9]|1[0-2]) - month
    • ((?:19|20)\d{2}) - year
  • ) - end of the group
  • \b - word boundary.

See the regex demo.

See a Dart demo:


void main() {
  final text = '13022020 and 20200213 20111919';
  print(text.replaceAllMapped(RegExp(r'\b(?:((?:19|20)\d{2})(0?[1-9]|1[0-2])(0?[1-9]|[12][0-9]|3[01])|(0?[1-9]|[12][0-9]|3[01])(0?[1-9]|1[0-2])((?:19|20)\d{2}))\b'), (Match m) => 
   m[4] == null ? "${m[1]}.${m[2]}.${m[3]}" : "${m[4]}.${m[5]}.${m[6]}"));
} 

Returning 13.02.2020 and 2020.02.13 20.11.1919.

If Group 4 is null, the first alternative matched, so we need to use Group 1, 2 and 3. Else, we join Group 4, 5 and 6 with a dot.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563