Map string to string "pattern" - need fast solution

Hi all.
I have a database that saves dates in the follwing format as plain strings: yyyymmddhhmmssiii (iii is miliseconds).

I want to convert this into a readable date string. I need this as a high performance function as I don't know how often it will be used later, in worst case, someone might use it without caching.

So what I look for is something like this:
Response.Write(DBstringToReadableString("dd.mm.yyyy hh:mm:ss", "20060320175422777")

Then this function should take the second string and map all elements as needed in the first string and return:
"20.03.2006 17:54:22"

As I need this as a very fast code, I assume someone could hanlde this with regEx... but I have no idea how you would do that without a lot IFs... anyone any idea please?
SmoerbleAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Fernando SotoRetiredCommented:
Hi  Smoerble;

The following code uses Regular Expression to reformat the text string to the correct format.

using System.Text.RegularExpressions;

        // Place these two statements at class level so that they are the most
        // high efficiency.
      private Regex re = new Regex(@"(?<yy>\d{4})(?<mm>\d\d)(?<dd>\d\d)" +
            @"(?<hh>\d\d)(?<min>\d\d)(?<ss>\d\d)(?<iii>\d{3})",
            RegexOptions.Compiled);
      private string replacePattern = "${dd}.${mm}.${yy} ${hh}:${min}:${ss}";

Then in your code insert the second line only, the string dateFormatted will have the date in the new format.

      string date = "20060320175422777"; // Test Data
      string dateFormatted = re.Replace( date, replacePattern);


I hope that this is of some help.

Fernando
SmoerbleAuthor Commented:
Cool, will try it immediately.

Question about performance:
You say, if I add a HelperClass and then add this as a function this will be slower? If yes, will you recognize this performance issue if you use it 500 times on a page?

Example
string myDate = HelperDates.convertToFromatted("20060320175422777);
Fernando SotoRetiredCommented:
Hi Smoerble;

The Regex class will compile the expression into low level code and do it once when created. Then it will use that low level code each time the function is called. If you place these two lines inside a function you will be creating the objects over and over again with out the need to do so. Place these definitions in a location where they may be accessed by all that need it so you may want to deine them as follows

        // Place these two statements at class level so that they are the most
        // high efficiency.
     public static Regex re = new Regex(@"(?<yy>\d{4})(?<mm>\d\d)(?<dd>\d\d)" +
          @"(?<hh>\d\d)(?<min>\d\d)(?<ss>\d\d)(?<iii>\d{3})",
          RegexOptions.Compiled);
     public static string replacePattern = "${dd}.${mm}.${yy} ${hh}:${min}:${ss}";

Fernando

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Rowby Goren Makes an Impact on Screen and Online

Learn about longtime user Rowby Goren and his great contributions to the site. We explore his method for posing questions that are likely to yield a solution, and take a look at how his career transformed from a Hollywood writer to a website entrepreneur.

Expert1701Commented:
As far as performance goes, here is a test with different techniques:

  using System;

  class Program
  {
    const int FormattedLength = 19; //"dd.MM.yyyy HH:mm:ss".Length

    static void Main(string[] args)
    {
      const int loops = 1000000;
   
      long start = DateTime.Now.Ticks;
      for(int i = 0; i < loops; ++i)
      {
        Replace1("20060320175422777");
      }
      System.Diagnostics.Debug.WriteLine("Replace1: " + (DateTime.Now.Ticks - start)/10000 + " ms");
   
      start = DateTime.Now.Ticks;
      for(int i = 0; i < loops; ++i)
      {
        Replace2("20060320175422777");
      }
      System.Diagnostics.Debug.WriteLine("Replace2: " + (DateTime.Now.Ticks - start)/10000 + " ms");

      start = DateTime.Now.Ticks;
      for(int i = 0; i < loops; ++i)
      {
        Replace3("20060320175422777");
      }
      System.Diagnostics.Debug.WriteLine("Replace3: " + (DateTime.Now.Ticks - start)/10000 + " ms");

      start = DateTime.Now.Ticks;
      for(int i = 0; i < loops; ++i)
      {
        Replace4("20060320175422777");
      }
      System.Diagnostics.Debug.WriteLine("Replace4: " + (DateTime.Now.Ticks - start)/10000 + " ms");
    }

    static System.Text.RegularExpressions.Regex re = new System.Text.RegularExpressions.Regex(@"(?<yy>\d{4})(?<mm>\d\d)(?<dd>\d\d)" + @"(?<hh>\d\d)(?<min>\d\d)(?<ss>\d\d)(?<iii>\d{3})", System.Text.RegularExpressions.RegexOptions.Compiled);
    const string replacePattern = "${dd}.${mm}.${yy} ${hh}:${min}:${ss}";

    static string Replace1(string date)
    {
      return re.Replace(date, replacePattern);
    }

    static System.Text.StringBuilder builder = new System.Text.StringBuilder(FormattedLength);

    static string Replace2(string date)
    {
      builder.Length = 0;

      builder.Append(date.Substring(6, 2));
      builder.Append(".");
      builder.Append(date.Substring(4, 2));
      builder.Append(".");
      builder.Append(date.Substring(0, 4));
      builder.Append(" ");
      builder.Append(date.Substring(8, 2));
      builder.Append(":");
      builder.Append(date.Substring(10, 2));
      builder.Append(":");
      builder.Append(date.Substring(12, 2));
     
      return builder.ToString();
    }

    public static string Replace3(string date)
    {
      return date.Substring(6, 2) + "." + date.Substring(4, 2) + "." + date.Substring(0, 4) + " " + date.Substring(8, 2) + ":" + date.Substring(10, 2) + ":" + date.Substring(12, 2);
    }

    public static string Replace4(string date)
    {
      char[] array = new char[]
        {
          date[6], date[7], '.',
          date[4], date[5], '.',
          date[0], date[1], date[2], date[3], '.',
          ' ',
          date[8], date[9], ':',
          date[10], date[11], ':',
          date[12], date[13]      
        };
                 
      return new string(array);
    }
  }

On my system, the output was:

  Replace1: 7968 ms
  Replace2: 1687 ms
  Replace3: 1187 ms
  Replace4: 578 ms

However, if you are only calling these functions 500 times, the difference is negligible.
Expert1701Commented:
Finally, if you really want performance, you could use unsafe code...

  public static string Replace5(string date)
  {
    string newDate = new string(' ', FormattedLength);
    unsafe
    {
      fixed(char* pDate = newDate)
      {
        pDate[0] = date[6];
        pDate[1] = date[7];
        pDate[2] = '.';
        pDate[3] = date[4];
        pDate[4] = date[5];
        pDate[5] = '.';
        pDate[6] = date[0];
        pDate[7] = date[1];
        pDate[8] = date[2];
        pDate[9] = date[3];
        pDate[10] = ' ';
        pDate[11] = date[8];
        pDate[12] = date[9];
        pDate[13] = ':';
        pDate[14] = date[10];
        pDate[15] = date[11];
        pDate[16] = ':';
        pDate[17] = date[12];
        pDate[18] = date[13];
      }
    }
    return newDate;
  }

Output:

  Replace5: 265 ms
KelmenCommented:
why not to have a dedicated Date\Time field in the table?
so the work at the coding.
SmoerbleAuthor Commented:
@Kelmen:
I have to work with an existing DB and can't change the formats as I wish :(. Sorry not to mention it at first.

@Expert:
Wow. Thanks for this test, this is very very helpful. Can you give me a pointer to an explanation what "unsafe code" is?

@Fernando:
Thanks for the solution, works as designed :). Will spare points between you and Expert because of his tremendous test, hope you don't mind?
Bob LearnedCommented:
You could do a DateTime.ParseExact, which will be considerably faster than a regular expression.

Bob
Expert1701Commented:
 public static string Replace6(string date)
  {
    DateTime dateTime = DateTime.ParseExact(date, "yyyyMMddHHmmssfff", System.Globalization.CultureInfo.InvariantCulture);
    return dateTime.ToString("dd/MM/yyyy HH:mm:ss");
  }

  Replace6: 11906 ms
Bob LearnedCommented:
See, like that ^^

Bob
SmoerbleAuthor Commented:
@Expert:
Can you give me a pointer to an explanation/tutorial what "unsafe code" is?

Fernando SotoRetiredCommented:
Hi Bob;

I would like to get credit for answering this question as well seeming I gave the first working solution. The following statement was made by the author Smoerble.

@Fernando:
Thanks for the solution, works as designed :). Will spare points between you and Expert because of his tremendous test, hope you don't mind?

Thanks;

Fernando


It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.