Utworzenie daty na podstawie ciągu znaków

Utworzenie daty na podstawie ciągu znaków
  • Rejestracja: dni
  • Ostatnio: dni
0

Jak w ładny sposób z ciągu np. 140927 r/m/d utworzyć datę 2014.09.27 ? Może

Kopiuj
Stringbuilder

albo

Kopiuj
DateTime

ale za ładnie/wydajnie to mi się nie wydaje że to będzie. Ten ciąg jest wczytywany z pliku txt.

MK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 33
0

Może tak:

Kopiuj
 
  string sth = "140927";
  var dt = DateTime.ParseExact( sth,"yyMMdd", CultureInfo.InvariantCulture);
  • Rejestracja: dni
  • Ostatnio: dni
0

Krótszy kod, ale wydajność gorsza od Stringbuildera.

MK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 33
0

Ale co dokładnie chcesz osiągnąć? Wklej swój kod. Chcesz datę czy string daty?

  • Rejestracja: dni
  • Ostatnio: dni
0

string.

Potrzebuję tylko jednę datę. Mniej więcej coś takiego:

Kopiuj
 StringBuilder sb = new StringBuilder("20");        
 sb.Append(List[List.Count - 1].Substring(0, 2));
 sb.Append(".");
 sb.Append(List[List.Count - 1].Substring(2, 2));
 sb.Append(".");
 sb.Append(List[List.Count - 1].Substring(4, 2));
 return sb.ToString(); 
Azarien
  • Rejestracja: dni
  • Ostatnio: dni
0

Krótszy kod, ale wydajność gorsza od Stringbuildera.
Robisz to milion razy że ma znaczenie?

MK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 33
0

Jeżeli chodzi o sam string, dalsza optymalizacja nie ma już większego sensu. Zamiast substring możesz użyć bezpośredniego odwołania elementów, ale to są dziesiątki ms przy millionie powtórzeń, więc gra nie warta świeczki.
Jeżeli natomiast nie zależy Ci na zmniejszaniu czasu wykonania, a nie chcesz robić tego przez podaną metodę z DateTime, żeby kod był czytelniejszy możesz użyć np.:

Kopiuj
      StringBuilder sb = new StringBuilder();
                var dt = sb.AppendFormat("20{0}.{1}.{2}",
                                        z.Substring(0, 2), 
                                        z.Substring(2, 2),
                                        z.Substring(4, 2)).ToString();

 
Azarien
  • Rejestracja: dni
  • Ostatnio: dni
0

@mkr: no to StringBuilder staje się w ogóle niepotrzebny:

Kopiuj
var dt = String.Format("20{0}.{1}.{2}",
                      z.Substring(0, 2), 
                      z.Substring(2, 2),
                      z.Substring(4, 2));
DibbyDum
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Polska, Kraków
2

To może tak:

Kopiuj
var dt = string.Format("20{0}{1}.{2}{3}.{4}{5}",
            z[0], z[1], z[2], z[3], z[4], z[5]);

:D

MK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 33
0

@_13th_Dragon gdzie popełniam błąd w swoim myśleniu:

Kopiuj
class TestClass
    {
        public List<string> Base { get; set; }
        public TestClass()
        {
            this.Base = new List<string>();
            GenFakeBase();            
        }

             public void FormatStringTest()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            foreach (var z in this.Base) {
                var dt = String.Format("20{0}.{1}.{2}",
                                       z.Substring(0, 2),
                                       z.Substring(2, 2),
                                       z.Substring(4, 2));
            }
            sw.Stop();
            Console.WriteLine(sw.Elapsed);
        }

      
        public void StringBuilderFormatTest()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            foreach (var z in this.Base)
            {
                StringBuilder sb = new StringBuilder();
                var dt = sb.AppendFormat("20{0}.{1}.{2}",
                                        z.Substring(0, 2), 
                                        z.Substring(2, 2),
                                        z.Substring(4, 2)).ToString();
           
            }
            sw.Stop();
            Console.WriteLine(sw.Elapsed);
        }
     
        private void GenFakeBase()
        {
            Random r = new Random();
          
            for (int i = 0; i < 4000000; i++)
            {
                this.Base.Add(String.Format("{0:yyMMdd}",
                              new DateTime(r.Next(2000, 2099), r.Next(1, 12), r.Next(1, 25))));
            }                         
            
        }
    }
 

Output:

Kopiuj
 
FormatStringTest: 00:00:00.6319586
StringBuilderFormatTest: 00:00:00.6164244

Edit:
Wytłumaczenie dlaczego:
http://stackoverflow.com/a/6824

_13th_Dragon
  • Rejestracja: dni
  • Ostatnio: dni
1
mkr napisał(a):

@_13th_Dragon gdzie popełniam błąd w swoim myśleniu:

  1. Jeżeli podajesz testy to podawaj tak aby można było odpalić
  2. Na starcie program dostaje nieco mniej czasu systemowego ponieważ zostaje mu policzony sam start (ładowanie do pamięci) więc pierwszy wynik zawsze gorszy
  3. Aby coś mówić o czasach musisz mieć czasy liczone w minutach lub zrobić przynajmniej 10 pomiarów i je uśrednić.

http://ideone.com/O365uh

Azarien
  • Rejestracja: dni
  • Ostatnio: dni
2

FormatStringTest: 00:00:00.6319586
StringBuilderFormatTest: 00:00:00.6164244

To jest 2% różnica w granicy błędu pomiaru. Patrz na to:

Kopiuj
FormatStringTest:
00:00:05.5449600
00:00:05.4707517
00:00:05.0750559

StringBuilderFormatTest:
00:00:04.4070724
00:00:04.3707764
00:00:04.3315935

To już jest 20-procentowa różnica.

.NET 3.5 na Pentium 4 (2.4 GHz), system 32-bitowy

MK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 33
0

Jeżeli string.Format wykorzystuje StringBulider.AppendFormat to jak może być szybsze, skoro dodatkowo sprawdza warunki i wykonuje operacje arytmetyczne?
Pytam bo nie wiem.

Na mojej konfiguracji test @_13th_Dragon, dla 10mln:

Kopiuj
StringBuilderFormatTest: 00:00:01.5849949
FormatStringTest: 00:00:01.6064279
StringBuilderFormatTest: 00:00:01.5818493
FormatStringTest: 00:00:01.6310405
StringBuilderFormatTest: 00:00:01.5696752
FormatStringTest: 00:00:01.6012421
StringBuilderFormatTest: 00:00:01.5687627
FormatStringTest: 00:00:01.5957641
StringBuilderFormatTest: 00:00:01.5678932
FormatStringTest: 00:00:01.5968718
StringBuilderFormatTest: 00:00:01.5839259
FormatStringTest: 00:00:01.5899373
StringBuilderFormatTest: 00:00:01.5626319
FormatStringTest: 00:00:01.6167412
StringBuilderFormatTest: 00:00:01.5615933
FormatStringTest: 00:00:01.6005508
StringBuilderFormatTest: 00:00:01.5598783
FormatStringTest: 00:00:01.6258477
StringBuilderFormatTest: 00:00:01.5630360
FormatStringTest: 00:00:01.6113027
 

Nadal utrzymuję, że na mojej konfiguracji jest StrinBuilder.AppendFormat() nieznacząco szybszy :)
Oczywiście wiem, że ta rozmowa nie ma sensu praktycznego i nikt nie patrzy na ms przy 10mln operacji.

M6
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 220
0
Azarien napisał(a):

FormatStringTest: 00:00:00.6319586
StringBuilderFormatTest: 00:00:00.6164244

To jest 2% różnica w granicy błędu pomiaru. Patrz na to:

Kopiuj
FormatStringTest:
00:00:05.5449600
00:00:05.4707517
00:00:05.0750559

StringBuilderFormatTest:
00:00:04.4070724
00:00:04.3707764
00:00:04.3315935

To już jest 20-procentowa różnica.

.NET 3.5 na Pentium 4 (2.4 GHz), system 32-bitowy

czemu uwazasz ze jest to blad pomiaru? StopWatch to chyba QueryPerformanceCounter a tam dokladnosc jest bardzo duza

Azarien
  • Rejestracja: dni
  • Ostatnio: dni
0

czemu uwazasz ze jest to blad pomiaru?
Bo nie robi się pomiarów czasu, jeśli różnica jest rzędu setnych sekundy.

Jeżeli string.Format wykorzystuje StringBulider.AppendFormat to jak może być szybsze, skoro dodatkowo sprawdza warunki i wykonuje operacje arytmetyczne?

Bo AppendFormat() używa StringBuildera, ale nie robi new StringBuilder(), tylko najwyraźniej pobiera z jakiejś puli wcześniej utworzonych StringBuilderów:

Kopiuj
            StringBuilder sb = StringBuilderCache.Acquire(format.Length + args.Length * 8);
            sb.AppendFormat(provider,format,args);
            return StringBuilderCache.GetStringAndRelease(sb);

Dlaczego tak to zrobili? Trudno powiedzieć. Może chodziło o prędkość (u nich tak było szybciej, u ciebie nie), a może o unikanie alokacji pamięci i obciążanie garbage collectora.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.