We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you a podcast all about Citrix Workspace, moving to the cloud, and analytics & intelligence. Episode 2 coming soon!Listen Now

x

Map string to string "pattern" - need fast solution

Smoerble
Smoerble asked
on
Medium Priority
263 Views
Last Modified: 2012-08-13
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?
Comment
Watch Question

Fernando SotoRetired
CERTIFIED EXPERT
Distinguished Expert 2017

Commented:
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

Author

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);
Retired
CERTIFIED EXPERT
Distinguished Expert 2017
Commented:
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

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
Top Expert 2006
Commented:
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.
Top Expert 2006

Commented:
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

Commented:
why not to have a dedicated Date\Time field in the table?
so the work at the coding.

Author

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?
CERTIFIED EXPERT
Most Valuable Expert 2012
Top Expert 2008

Commented:
You could do a DateTime.ParseExact, which will be considerably faster than a regular expression.

Bob
Top Expert 2006

Commented:
 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
CERTIFIED EXPERT
Most Valuable Expert 2012
Top Expert 2008

Commented:
See, like that ^^

Bob

Author

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

CERTIFIED EXPERT
Most Valuable Expert 2012
Top Expert 2008

Commented:
Fernando SotoRetired
CERTIFIED EXPERT
Distinguished Expert 2017

Commented:
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


Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.