6

Question - what is the shortest form of regex to add a leading zero into single digit in date record?

So I want to convert 8/8/2014 8:04:34 to 08/08/2014 8:04:34 - add leading zero when only one digit is presented.

The record can have two single digit entry, one single digit entry or no single digit entry. Some records can be in forms like 25/06/2014 19:50:18 or 9/06/2014 8:27:35 - in other words, some of them could be already normalized and regex needs to fix only single digit entry.

Not a regex user by any means. Your help is appreciated.

Invisible999
  • 547
  • 2
  • 5
  • 16

7 Answers7

7

How about:

  • Ctrl+H
  • Find what: \b(\d)(?=/)
  • Replace with: 0$1
  • Replace all

This will change 8/8/2014 8:04:34 into 08/08/2014 8:04:34

Toto
  • 89,455
  • 62
  • 89
  • 125
  • 1
    This is incredibly simple and effective, but you have to watch out for undesired matches: the OP said he wanted to replace `8/8/2014 8:04:34` with `08/08/2014 8:04:34`, that is, only the date should be changed, but not the time. Your solution also changes the time (and any other single digit in the file), so it must be used carefully. Anyway it's a good answer; if you edit your answer and add a note about this, you'll have my upvote. – Fabio says Reinstate Monica May 11 '16 at 12:31
  • @FabioTurati: You're right, I've edited the answer in this way. – Toto May 11 '16 at 14:01
4

Use the following regex to find:

(\d)(\d)?/(\d)(\d)?/(.*)

Then use the following to replace:

(?{2}\1\2:0\1)/(?{4}\3\4:0\3)/\5

What we are using is called conditionals in terms of regex. Refer this answer for explanation.

Make sure you have unselected the checkbox which says ". matches newline".

Community
  • 1
  • 1
CinCout
  • 9,486
  • 12
  • 49
  • 67
2

First of all, let's do some test-driven development and write the test cases. We can ignore the time and concentrate on the date alone. Also, the year is not important. We have to find all the possible cases for the day and the month. For each of them, we can have:

  • A single digit
  • Two digits, the first of which is already a 0
  • Two digits, the first of which is not a 0
  • Two digits, the second of which is a 0 (probably not needed, but just in case).

The case where we have to do something is only the first one, and the last 3 could be joined into a single one, but I prefer to keep them separated. We need to test 16 combinations:

8/8/2014
8/08/2014
8/12/2014
8/10/2014

08/8/2014
08/08/2014
08/12/2014
08/10/2014

12/8/2014
12/08/2014
12/12/2014
12/10/2014

10/8/2014
10/08/2014
10/12/2014
10/10/2014

Of all of these, only 1, 2, 3, 4, 5, 9, 13 must be changed. I don't know how to do it with a single regex, but with 2 regexes it's easy:

First regex, for the day:

(?<!\d)(\d/\d{1,2}/\d+)

replace with:

0\1

It matches a date where the day has only one digit, followed by a month with either 1 or 2 days, followed by a year with any number of digits, and it simply adds a 0 at the beginning.

Second regex, for the month:

(\d{2}/)(\d/\d+)

replace with:

\10\2

This one assumes that the first one has already been run, and thus the day has 2 digits. It finds dates where the month has a single digit, and adds a 0 before it. Please note that \10\2 means: the first group that matched, followed by a 0, followed by the second group. It doesn't mean: the tenth group, followed by the second. So the digits 1 and 0 are logically separated.

Run the first one, then the second one, and it gives the correct result:

08/08/2014
08/08/2014
08/12/2014
08/10/2014

08/08/2014
08/08/2014
08/12/2014
08/10/2014

12/08/2014
12/08/2014
12/12/2014
12/10/2014

10/08/2014
10/08/2014
10/12/2014
10/10/2014
1

Thanks to this recent answer I finally can give you an (hopefully) correct answer ;)

Replace

\b(?:(\d\d)|(\d))/(?:(\d\d)|(\d))/(\d\d)

with

(?{1}\1:0$2)/(?{3}\3:0\4)/\5

It uses Notepad++ conditionals (which I didn't know of until I stumbled over the mention question) to handle when only one or the other is single digit.

The regex matches a word boundary \b followed by two digits, captured in group 1, or one digit, captured in group 2, followed by a /. Then the same logic is repeated for day, which is captured in group 3 (2 digit) or 4 (1 digit). Then finally it checks that a year follows (at least two digits).

The conditional replace is explained in the linked answer. But simply put the (?{1} test if a match to group 1 was made it replaces with the expression before the :, otherwise the one after.

Hope this helps.

Regards

Community
  • 1
  • 1
SamWhan
  • 8,296
  • 1
  • 18
  • 45
  • @FabioTurati Fixed :) – SamWhan May 11 '16 at 12:18
  • Yes, I've seen it. I actually deleted my comment seconds before you posted this :-). And I have to say that your solution is much more elegant than mine, though mine is easier to understand. I had no idea either that there could be conditionals in regexes, that's why I used two. Great job, +1! – Fabio says Reinstate Monica May 11 '16 at 12:22
0

If you had a date like (ISO format)

2017-9-5

This

replace(/(\D)(\d)(?!\d)/g, '$10$2')

will turn it into

2017-09-05

and will preserve two digits in dates like

2017-11-11 or 2017-9-05
Povesma Dmytro
  • 326
  • 2
  • 6
  • This will change hours `8:27:35` => `08:27:35`, that is not wanted – Toto Sep 05 '17 at 09:34
  • Replace \D (which is not a digit) to the symbols you need. So it will turn into smth like `replace(/(^|\/)(\d)(?=\/|\s)/g, '$10$2')` – Povesma Dmytro Sep 05 '17 at 09:40
  • Reread the question, they want regex in notepad++. Moreover, have you tried your regex on OP's example (ie `8/8/2014 8:04:34`)? – Toto Sep 05 '17 at 09:48
  • Yup. Question is not about notepad++ (tag? regexps can be used wherever). `> '8/8/2014 8:04:34'.replace(/(^|\/)(\d)(?=\/|\s|$)/g, '$10$2')` `'08/08/2014 8:04:34' ` – Povesma Dmytro Sep 05 '17 at 09:52
0

a general approach is to search for (in this case 5 digit numbers):

(\d)??(\d)??(\d)??(\d)??(\d)

Replace with

(?1\1:0)(?2\2:0)(?3\3:0)(?4\4:0)\5
  • Given `8/8/2014 8:04:34` this produces `00008/00008/20104 00008:00004:30004`, not really that is wanted! – Toto Mar 24 '20 at 14:09
0

You can use /^\d\/|(?<=\/)\d\/\d/g to select text, then add 0 before selected text, it should work for all your conditions.

  • "`then add 0 before selected text`", nice, but how to do that? – Toto Aug 12 '21 at 12:30
  • I use javascript where it can be done as ``"8/8/2014 8:04:34".replace(regex, str => `0${str}`)`` the output becomes `08/08/2014 8:04:34`. you should be able to add something before the text selected, in other languages/editors too, though I'm not aware of how. Sorry. – Subham Bhattacharjee Aug 12 '21 at 15:37
  • OP asked for a Notepad++ solution. – Toto Aug 12 '21 at 16:46
  • In that case use `/^\d\/|(?<=[\n\s])\d\/|(?<=\/)\d\/\d/g` regular expression then use replace with the string `0$&`. Added the `(?<=[\n\s])\d\/` to match date right after a space or a new line. The string `$&` is the string matched by the reg exp. So the string `0$&` adds 0 before the matched string as needed to do. [Here](https://stackoverflow.com/questions/283608/using-regex-to-prefix-and-append-in-notepad) is the reference stack overflow question for the `$0` string and [here](http://regexr.com/) is the direct reference. – Subham Bhattacharjee Aug 13 '21 at 04:11