• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 248
  • Last Modified:

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?
0
Smoerble
Asked:
Smoerble
  • 3
  • 3
  • 3
  • +2
2 Solutions
 
Fernando SotoCommented:
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
0
 
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);
0
 
Fernando SotoCommented:
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
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
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.
0
 
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
0
 
KelmenCommented:
why not to have a dedicated Date\Time field in the table?
so the work at the coding.
0
 
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?
0
 
Bob LearnedCommented:
You could do a DateTime.ParseExact, which will be considerably faster than a regular expression.

Bob
0
 
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
0
 
Bob LearnedCommented:
See, like that ^^

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

0
 
Fernando SotoCommented:
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


0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 3
  • 3
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now