Reputation: 24493
In Delphi XE2, I bumped against a strange formatting difference when formatting Currency
. Using Double
works as expected.
It looks that when using %F
or %N
(floating point or numeric) you always get 3 decimal digits, even if you request fewer.
'%.1f'
a Double
value of 3.1415
will become '3.1'
, but a Currency
value of 3.1415
will become '3.142'
(assuming en-US locale).'%4.0n'
a Double
value of 3.1415
will become ' 3'
, but a Currency
value of 3.1415
will become '3.142'
(assuming en-US locale).I wrote the below quick DUnit test case, and will investigate further tomorrow.
This particular project cannot be changed to anything other than Delphi XE2 (big corporates are not flexible in what tools they use), so I'm looking for a solution that solves this in Delphi XE2.
In the mean time: what are your thoughts?
unit TestSysUtilsFormatUnit;
interface
uses
TestFramework, System.SysUtils;
type
TestSysUtilsFormat = class(TTestCase)
strict private
DoublePi: Double;
CurrencyPi: Currency;
FloatFormat: string;
NumericFormat: string;
Expected_Format_F: string;
Expected_Format_N: string;
public
procedure SetUp; override;
procedure TearDown; override;
published
procedure Test_Format_F_Double;
procedure Test_Format_F_Currency;
procedure Test_Format_N_Double;
procedure Test_Format_N_Currency;
end;
implementation
procedure TestSysUtilsFormat.Test_Format_F_Double;
var
ReturnValue: string;
begin
ReturnValue := System.SysUtils.Format(FloatFormat, [DoublePi]);
Self.CheckEqualsString(Expected_Format_F, ReturnValue); // actual '3.1'
end;
procedure TestSysUtilsFormat.Test_Format_F_Currency;
var
ReturnValue: string;
begin
ReturnValue := System.SysUtils.Format(FloatFormat, [CurrencyPi]);
Self.CheckEqualsString(Expected_Format_F, ReturnValue); // actual '3.142'
end;
procedure TestSysUtilsFormat.Test_Format_N_Double;
var
ReturnValue: string;
begin
ReturnValue := System.SysUtils.Format(NumericFormat, [DoublePi]);
Self.CheckEqualsString(Expected_Format_N, ReturnValue); // actual ' 3'
end;
procedure TestSysUtilsFormat.Test_Format_N_Currency;
var
ReturnValue: string;
begin
ReturnValue := System.SysUtils.Format(NumericFormat, [CurrencyPi]);
Self.CheckEqualsString(Expected_Format_N, ReturnValue); // actual '3.142'
end;
procedure TestSysUtilsFormat.SetUp;
begin
DoublePi := 3.1415;
CurrencyPi := 3.1415;
FloatFormat := '%.1f';
Expected_Format_F := '3.1';
NumericFormat := '%4.0n';
Expected_Format_N := ' 3';
end;
procedure TestSysUtilsFormat.TearDown;
begin
end;
initialization
RegisterTest(TestSysUtilsFormat.Suite);
end.
Upvotes: 1
Views: 1331
Reputation: 24493
This was a bug in early Delphi XE 2 versions in these methods:
function WideFormatBuf(var Buffer; BufLen: Cardinal; const Format;
FmtLen: Cardinal; const Args: array of const;
const AFormatSettings: TFormatSettings): Cardinal;
function FormatBuf(var Buffer; BufLen: Cardinal; const Format;
FmtLen: Cardinal; const Args: array of const;
const AFormatSettings: TFormatSettings): Cardinal;
Fails:
(The odd thing is: that version indicates "no updates available" with starting the "check for updates")
I did not have time to check intermediate versions.
Works:
One of the things that XE2 Update 4 (with or without the hotfix) breaks is the creation of a standard (non-IntraWeb) unit test project.
This menu entry is missing: File -> New -> Other -> Unit Test -> Test Project.
As a reminder to myself, this is the skeleton code to quickly get started with the missing Test Project entry:
program UnitTest1;
{
Delphi DUnit Test Project
-------------------------
This project contains the DUnit test framework and the GUI/Console test runners.
Add "CONSOLE_TESTRUNNER" to the conditional defines entry in the project options
to use the console test runner. Otherwise the GUI test runner will be used by
default.
}
{$IFDEF CONSOLE_TESTRUNNER}
{$APPTYPE CONSOLE}
{$ENDIF}
uses
Forms,
TestFramework,
GUITestRunner,
TextTestRunner;
{$R *.RES}
begin
Application.Initialize;
if IsConsole then
with TextTestRunner.RunRegisteredTests do
Free
else
GUITestRunner.RunRegisteredTests;
end.
Upvotes: 0
Reputation: 125708
Posting this as an answer on the request of the asker in the comments to the question above.)
I can't reproduce the issue on either XE2 or XE3, with a plain console application. (It was just quicker to set up for me.)
Here's the code I used in it's entirely (on both XE2/XE3):
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
SysUtils;
const
DoublePi: Double = 3.1415;
CurrencyPi: Currency = 3.1415;
FloatFormat = '%.1f';
NumericFormat = '%4.0n';
begin
WriteLn(Format('Double (.1f) : '#9 + FloatFormat, [DoublePi]));
WriteLn(Format('Currency (.1f) : '#9 + FloatFormat, [CurrencyPi]));
WriteLn(Format('Currency (4.0n): '#9 + NumericFormat, [CurrencyPi]));
ReadLn;
end.
Here's the output from the XE2 run (Delphi® XE2 Version 16.0.4429.46931): :
Upvotes: 1