Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2008-04

TimeReFormat in FormatDateTime

10 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Unknown author

I do no know exact reason use TimeReFormat (replacing 'm'->'n' in time formating). But we cannot use this, because this breaks 'am/pm' and 'ampm' formating request. And we get 'Illegal character in format string'.

Here is little patch, which disables this behaviour.

Index: objpas/sysutils/dati.inc
=================================================================== --- objpas/sysutils/dati.inc (revision 10597)
+++ objpas/sysutils/dati.inc (working copy)
@@ -569,13 +569,13 @@

    Function TimeReFormat(Const S : string) : string;
    // Change m into n for time formatting.
-   Var i : longint;
+   //Var i : longint;
    begin
      Result:=S;
-     For I:=1 to Length(Result) do
+     {For I:=1 to Length(Result) do //We cannot do that am/pm does not then work
        If Result[i]='m' then
-         result[i]:='n';
+         result[i]:='n';}
    end;
 var

Petr

Ing. Petr Kristan . EPOS PRO s.r.o., Bozeny Nemcove 2625, 530 02 Pardubice tel: +420 466335223 Czech Republic (Eastern Europe) fax: +420 466510709

Reply by email

Michael Van Canneyt
to Unknown author
Show quoted text 5 lines
I do no know exact reason use TimeReFormat (replacing 'm'->'n' in time formating). But we cannot use this, because this breaks 'am/pm' and 'ampm' formating request. And we get 'Illegal character in format string'. Here is little patch, which disables this behaviour.

It should not be disabled, but fixed properly.
This code is there for a reason:

Normal time formatting is hh:nn (n = minutes). But Delphi explicitly allows also hh:mm for time, even though mm is the placeholder for month.

Michael.

Show quoted text 36 lines
Index: objpas/sysutils/dati.inc =================================================================== --- objpas/sysutils/dati.inc (revision 10597) +++ objpas/sysutils/dati.inc (working copy) @@ -569,13 +569,13 @@ Function TimeReFormat(Const S : string) : string; // Change m into n for time formatting. - Var i : longint; + //Var i : longint; begin Result:=S; - For I:=1 to Length(Result) do + {For I:=1 to Length(Result) do //We cannot do that am/pm does not then work If Result[i]='m' then - result[i]:='n'; + result[i]:='n';} end; var Petr -- Ing. Petr Kristan . EPOS PRO s.r.o., Bozeny Nemcove 2625, 530 02 Pardubice tel: +420 466335223 Czech Republic (Eastern Europe) fax: +420 466510709 _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Unknown author
to Michael Van Canneyt
Michael Van Canneyt wrote 15 lines
On Tue, 8 Apr 2008, wrote: > I do no know exact reason use TimeReFormat (replacing 'm'->'n' in time > formating). But we cannot use this, because this breaks 'am/pm' and 'ampm' formating request. > And we get 'Illegal character in format string'. > > Here is little patch, which disables this behaviour. It should not be disabled, but fixed properly. This code is there for a reason: Normal time formatting is hh:nn (n = minutes). But Delphi explicitly allows also hh:mm for time, even though mm is the placeholder for month.

But this feature works without TimeReFormat hack. Here is piece of code from dati.inc:

 'M': begin
       if lastformattoken='H' then
         begin
           if Count = 1 then
             StoreInt(Minute, 0)
           else
             StoreInt(Minute, 2);
         end
       else
         begin
           case Count of
              1: StoreInt(Month, 0);
              2: StoreInt(Month, 2);
              3: StoreString(ShortMonthNames[Month]);
              4: StoreString(LongMonthNames[Month]);
           end;
         end;
    end;

Next TimeReFormat cannot work correctly, because FormatString is case insensitive and comparison "If Result[i]='m'" leaves this out of account.

Petr

Show quoted text 21 lines
> Index: objpas/sysutils/dati.inc > =================================================================== > --- objpas/sysutils/dati.inc (revision 10597) > +++ objpas/sysutils/dati.inc (working copy) > @@ -569,13 +569,13 @@ > > Function TimeReFormat(Const S : string) : string; > // Change m into n for time formatting. > - Var i : longint; > + //Var i : longint; > > begin > Result:=S; > - For I:=1 to Length(Result) do > + {For I:=1 to Length(Result) do //We cannot do that am/pm does not then work > If Result[i]='m' then > - result[i]:='n'; > + result[i]:='n';} > end; > > var
Ing. Petr Kristan . EPOS PRO s.r.o., Bozeny Nemcove 2625, 530 02 Pardubice tel: +420 466335223 Czech Republic (Eastern Europe) fax: +420 466510709

Reply by email

Michael Van Canneyt
to Unknown author
Show quoted text 42 lines
On Tue, Apr 08, 2008 at 04:32:30PM +0200, Michael Van Canneyt wrote: > > > On Tue, 8 Apr 2008, wrote: > > > I do no know exact reason use TimeReFormat (replacing 'm'->'n' in time > > formating). But we cannot use this, because this breaks 'am/pm' and 'ampm' formating request. > > And we get 'Illegal character in format string'. > > > > Here is little patch, which disables this behaviour. > > It should not be disabled, but fixed properly. > This code is there for a reason: > > Normal time formatting is hh:nn (n = minutes). But Delphi explicitly > allows also hh:mm for time, even though mm is the placeholder for month. But this feature works without TimeReFormat hack. Here is piece of code from dati.inc: 'M': begin if lastformattoken='H' then begin if Count = 1 then StoreInt(Minute, 0) else StoreInt(Minute, 2); end else begin case Count of 1: StoreInt(Month, 0); 2: StoreInt(Month, 2); 3: StoreString(ShortMonthNames[Month]); 4: StoreString(LongMonthNames[Month]); end; end; end; Next TimeReFormat cannot work correctly, because FormatString is case insensitive and comparison "If Result[i]='m'" leaves this out of account.
Did you test it ? If you can confirm that hh:mm:ss works correctly, then
I'll apply the patch.

Michael.

Reply by email

Unknown author
to Michael Van Canneyt
Michael Van Canneyt wrote 49 lines
On Tue, 8 Apr 2008, wrote: > On Tue, Apr 08, 2008 at 04:32:30PM +0200, Michael Van Canneyt wrote: > > > > > > On Tue, 8 Apr 2008, wrote: > > > > > I do no know exact reason use TimeReFormat (replacing 'm'->'n' in time > > > formating). But we cannot use this, because this breaks 'am/pm' and 'ampm' formating request. > > > And we get 'Illegal character in format string'. > > > > > > Here is little patch, which disables this behaviour. > > > > It should not be disabled, but fixed properly. > > This code is there for a reason: > > > > Normal time formatting is hh:nn (n = minutes). But Delphi explicitly > > allows also hh:mm for time, even though mm is the placeholder for month. > But this feature works without TimeReFormat hack. Here is piece of code > from dati.inc: > > 'M': begin > if lastformattoken='H' then > begin > if Count = 1 then > StoreInt(Minute, 0) > else > StoreInt(Minute, 2); > > end > else > begin > case Count of > 1: StoreInt(Month, 0); > 2: StoreInt(Month, 2); > 3: StoreString(ShortMonthNames[Month]); > 4: StoreString(LongMonthNames[Month]); > end; > end; > end; > > Next TimeReFormat cannot work correctly, because FormatString is case > insensitive and comparison "If Result[i]='m'" leaves this out of account. Did you test it ? If you can confirm that hh:mm:ss works correctly, then I'll apply the patch.

Sure, I tested it. hh:mm:ss and hh:nn:ss works identically. But isn't cleaner solution remove TimeReFormat completly? I can redone the patch.

Petr

Ing. Petr Kristan . EPOS PRO s.r.o., Bozeny Nemcove 2625, 530 02 Pardubice tel: +420 466335223 Czech Republic (Eastern Europe) fax: +420 466510709

Reply by email

Michael Van Canneyt
to Unknown author
Show quoted text 52 lines
On Tue, Apr 08, 2008 at 05:23:04PM +0200, Michael Van Canneyt wrote: > > > On Tue, 8 Apr 2008, wrote: > > > On Tue, Apr 08, 2008 at 04:32:30PM +0200, Michael Van Canneyt wrote: > > > > > > > > > On Tue, 8 Apr 2008, wrote: > > > > > > > I do no know exact reason use TimeReFormat (replacing 'm'->'n' in time > > > > formating). But we cannot use this, because this breaks 'am/pm' and 'ampm' formating request. > > > > And we get 'Illegal character in format string'. > > > > > > > > Here is little patch, which disables this behaviour. > > > > > > It should not be disabled, but fixed properly. > > > This code is there for a reason: > > > > > > Normal time formatting is hh:nn (n = minutes). But Delphi explicitly > > > allows also hh:mm for time, even though mm is the placeholder for month. > > But this feature works without TimeReFormat hack. Here is piece of code > > from dati.inc: > > > > > 'M': begin > > if lastformattoken='H' then > > begin > > if Count = 1 then > > StoreInt(Minute, 0) > > else > > StoreInt(Minute, 2); > > > > end > > else > > begin > > case Count of > > 1: StoreInt(Month, 0); > > 2: StoreInt(Month, 2); > > 3: StoreString(ShortMonthNames[Month]); > > 4: StoreString(LongMonthNames[Month]); > > end; > > end; > > end; > > > > Next TimeReFormat cannot work correctly, because FormatString is case > > insensitive and comparison "If Result[i]='m'" leaves this out of account. > > Did you test it ? If you can confirm that hh:mm:ss works correctly, then > I'll apply the patch. Sure, I tested it. hh:mm:ss and hh:nn:ss works identically. But isn't cleaner solution remove TimeReFormat completly?

I meant: did you test with TimeReFormat removed ? :)

Michael.

Reply by email

Unknown author
to Michael Van Canneyt
Michael Van Canneyt wrote 58 lines
On Tue, 8 Apr 2008, wrote: > On Tue, Apr 08, 2008 at 05:23:04PM +0200, Michael Van Canneyt wrote: > > > > > > On Tue, 8 Apr 2008, wrote: > > > > > On Tue, Apr 08, 2008 at 04:32:30PM +0200, Michael Van Canneyt wrote: > > > > > > > > > > > > On Tue, 8 Apr 2008, wrote: > > > > > > > > > I do no know exact reason use TimeReFormat (replacing 'm'->'n' in time > > > > > formating). But we cannot use this, because this breaks 'am/pm' and 'ampm' formating request. > > > > > And we get 'Illegal character in format string'. > > > > > > > > > > Here is little patch, which disables this behaviour. > > > > > > > > It should not be disabled, but fixed properly. > > > > This code is there for a reason: > > > > > > > > Normal time formatting is hh:nn (n = minutes). But Delphi explicitly > > > > allows also hh:mm for time, even though mm is the placeholder for month. > > > But this feature works without TimeReFormat hack. Here is piece of code > > > from dati.inc: > > > > > > > > 'M': begin > > > if lastformattoken='H' then > > > begin > > > if Count = 1 then > > > StoreInt(Minute, 0) > > > else > > > StoreInt(Minute, 2); > > > > > > end > > > else > > > begin > > > case Count of > > > 1: StoreInt(Month, 0); > > > 2: StoreInt(Month, 2); > > > 3: StoreString(ShortMonthNames[Month]); > > > 4: StoreString(LongMonthNames[Month]); > > > end; > > > end; > > > end; > > > > > > Next TimeReFormat cannot work correctly, because FormatString is case > > > insensitive and comparison "If Result[i]='m'" leaves this out of account. > > > > Did you test it ? If you can confirm that hh:mm:ss works correctly, then > > I'll apply the patch. > Sure, I tested it. hh:mm:ss and hh:nn:ss works identically. > But isn't cleaner solution remove TimeReFormat completly? I meant: did you test with TimeReFormat removed ? :)

Yes. I tested it with dissabled functionality of TimeReFormat:

   Function TimeReFormat(Const S : string) : string;
   // Change m into n for time formatting.
   //Var i : longint;
   begin
     Result:=S;
     {For I:=1 to Length(Result) do //We cannot do that, am/pm does not then work
       If Result[i]='m' then
         result[i]:='n';}
   end;

But I think, that cleaner will be remove function TimeReFormat completly not only dissable functionality (superfluous call).

Petr

Ing. Petr Kristan . EPOS PRO s.r.o., Bozeny Nemcove 2625, 530 02 Pardubice tel: +420 466335223 Czech Republic (Eastern Europe) fax: +420 466510709

Reply by email

Unknown author
to Unknown author
Show quoted text 74 lines
On Tue, Apr 08, 2008 at 05:54:40PM +0200, Michael Van Canneyt wrote: > > > On Tue, 8 Apr 2008, wrote: > > > On Tue, Apr 08, 2008 at 05:23:04PM +0200, Michael Van Canneyt wrote: > > > > > > > > > On Tue, 8 Apr 2008, wrote: > > > > > > > On Tue, Apr 08, 2008 at 04:32:30PM +0200, Michael Van Canneyt wrote: > > > > > > > > > > > > > > > On Tue, 8 Apr 2008, wrote: > > > > > > > > > > > I do no know exact reason use TimeReFormat (replacing 'm'->'n' in time > > > > > > formating). But we cannot use this, because this breaks 'am/pm' and 'ampm' formating request. > > > > > > And we get 'Illegal character in format string'. > > > > > > > > > > > > Here is little patch, which disables this behaviour. > > > > > > > > > > It should not be disabled, but fixed properly. > > > > > This code is there for a reason: > > > > > > > > > > Normal time formatting is hh:nn (n = minutes). But Delphi explicitly > > > > > allows also hh:mm for time, even though mm is the placeholder for month. > > > > But this feature works without TimeReFormat hack. Here is piece of code > > > > from dati.inc: > > > > > > > > > > > 'M': begin > > > > if lastformattoken='H' then > > > > begin > > > > if Count = 1 then > > > > StoreInt(Minute, 0) > > > > else > > > > StoreInt(Minute, 2); > > > > > > > > end > > > > else > > > > begin > > > > case Count of > > > > 1: StoreInt(Month, 0); > > > > 2: StoreInt(Month, 2); > > > > 3: StoreString(ShortMonthNames[Month]); > > > > 4: StoreString(LongMonthNames[Month]); > > > > end; > > > > end; > > > > end; > > > > > > > > Next TimeReFormat cannot work correctly, because FormatString is case > > > > insensitive and comparison "If Result[i]='m'" leaves this out of account. > > > > > > Did you test it ? If you can confirm that hh:mm:ss works correctly, then > > > I'll apply the patch. > > Sure, I tested it. hh:mm:ss and hh:nn:ss works identically. > > But isn't cleaner solution remove TimeReFormat completly? > > I meant: did you test with TimeReFormat removed ? :) Yes. I tested it with dissabled functionality of TimeReFormat: Function TimeReFormat(Const S : string) : string; // Change m into n for time formatting. //Var i : longint; begin Result:=S; {For I:=1 to Length(Result) do //We cannot do that, am/pm does not then work If Result[i]='m' then result[i]:='n';} end; But I think, that cleaner will be remove function TimeReFormat completly not only dissable functionality (superfluous call).

In the attachment is patch with TimeReFormat removed. Patch is tested, hh:mm:ss and hh:nn:ss works identically.

Petr

Ing. Petr Kristan . EPOS PRO s.r.o., Bozeny Nemcove 2625, 530 02 Pardubice tel: +420 466335223 Czech Republic (Eastern Europe) fax: +420 466510709

Reply by email

Sergei Gorelkin
to Michael Van Canneyt: It should not be disabled, but fixed properly. This code is there for a reason: Normal…
Michael Van Canneyt wrote 7 lines
It should not be disabled, but fixed properly. This code is there for a reason: Normal time formatting is hh:nn (n = minutes). But Delphi explicitly allows also hh:mm for time, even though mm is the placeholder for month.

I have a more complex patch, that fixes this issue together with a number of others. Have a look.

a) Enables threadsafe versions of date/time formatting functions (this was primary goal of the patching).
b) Favours case of AM/PM and A/P tokens, as Delphi does. c) More tolerant to mistakes in format strings (e.g. 'mmmmm' and longer will be treated as 'mmmm'; empty format string is treated as 'c' - again Delphi compatible).
d) Prevents possibility of endless recursion in certain cases of malformed format settings, e.g. when ShortTimeFormat contains 't'. Since format settings may come from anywhere (including untrusted sources), this is an important security issue.
e) Refactored to exclude ansistring operations (except final setting of result), this should increase performance.

As for TimeReformat, I excluded it primarily for performance reasons, substituting with a flag that causes 'm' be treated as 'n' even if it is not preceded by 'h'. This preserves existing logic as much as possible, but am/pm tokens won't be affected because they are handled in another branch of code.

The patch also refactors CurrentYear function to exclude unnecessary date encoding and decoding.

I tested it locally on Russian locale and it works fine, however I cannot guarantee that everything is correct on every locale.

Best regards,
Sergei

Reply by email

Michael Van Canneyt
to Unknown author: In the attachment is patch with TimeReFormat removed. Patch is tested, hh:mm:ss and…
Show quoted text 17 lines
> Yes. I tested it with dissabled functionality of TimeReFormat: > > Function TimeReFormat(Const S : string) : string; > // Change m into n for time formatting. > //Var i : longint; > > begin > Result:=S; > {For I:=1 to Length(Result) do //We cannot do that, am/pm does not then work > If Result[i]='m' then > result[i]:='n';} > end; > > But I think, that cleaner will be remove function TimeReFormat completly > not only dissable functionality (superfluous call). In the attachment is patch with TimeReFormat removed. Patch is tested, hh:mm:ss and hh:nn:ss works identically.

Excellent. I committed the patch, thank you very much !

Michael.

Reply by email