DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: monica9612
今日帖子: 1
在线用户: 9
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 kylix2008 (kylix2008) ★☆☆☆☆ -
普通会员
2019/5/6 16:48:50
标题:
cxGrid不支持小日期吗? 浏览:1857
加入我的收藏
楼主: PL/SQL Devloper中查得某表的某个记录DJRQ(登记日期)字段值为0030-01-30(YYYY-MM-DD格式),在Delphi IDE下调试运行,在cxGrid中显示该表,滚动到该字段(cxGrid中显示空白),并且弹出出错提示:Rrased EVariantInvalidArgError with message "Invalid argument"。


fValue:Variant;
DValue:TDataTime;
...

fValue:= cxCustomGridRecord.Values(i);  //将该登记日期字段的值0030-01-30赋给fValue。
运行到上句,调试时显示fValue值为Delphi Exception EVariantInvalidArgError as $5277F8E9,但程序不会弹出出错,继续运行到
DValue:=StrToDataTime(fValue,0);
出错: EVariantInvalidArgError with message "Invalid argument"

啥原因呢?日期值太小,超出转换范围了?

DevExpress版本为16.x, delphi XE3

似乎DevExpress或delphi日期支持的最小值为0100-01-01,若是这样,如何解决上面的问题?
----------------------------------------------
-
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2019/5/6 18:42:11
1楼: NOTE: use DEBUG to see what value is in fVAlue and DValue

----------
Maybe:

var
  fValueDateTime:TDateTime;
begin
  fValueDateTime:= cxCustomGridRecord.Values(i); // no error if TDateTime
  //
  // if Values(i) = String 
  //  fValueDateTime:= StrToDateTime( cxCustomGridRecord.Values(i) ); 
  //

// System.Utils.pas
//
// TryStrToDate()
// TryStrToDateTime()
// EncodeDate()
// EncodeTime()
// DecodeTime();
// DecodeDate();
// DecodeDateFully()
  ...
end;

----------
DevExpress:

Type: DateTime 
A System.DateTime structure which represents the minimum allowed date. 

Use the MinDate and MaxDate properties to limit user input to dates falling within a specific range. The MinDate property specifies the low limit of the allowed date range.

Dates which are out of the specified range cannot be entered into the date editor by end-users either by typing within the editor's edit box or using the dropdown calendar. In the dropdown calendar, these dates are displayed using a specific style (CalendarProperties.DayOutOfRangeStyle) and don't respond to user clicks. When an end-user types an unavailable date in the editor's edit box, a warning message is displayed if the ShowOutOfRangeWarning property is set to true. After the editor loses focus, the date automatically changes to the last specified allowed date.

Note that programmatic manipulation on the date editor's value isn't limited by the MinDate and MaxDate property values.

----------
You can use the following approach to set the MinDate property of TcxBarEditItem with DateEdit:
[Delphi]Open in popup window
  (TcxBarEditItem.Properties as TcxDateEditProperties).MinDate := <ADate>;

----------
DevExpress 18.2.1 VCL Delphi 10.3.1

cxDateNavigator1.Date := EncodeDate(1,12,31); // YYYY-MM-DD = OK

----------

DevExpress type DateTime is equal Delphi System.DateTime type

----------

Example using cxDateNavigator:

// Year = 1, Month = 12, Day = 31
cxDateNavigator1.Date := EncodeDate(1,12,31); ===> OK is accept an not error is generated.

BUT... the buttons   <  and  > from cxDateNavigator stay frozed (dont work)  BUT if you use the keyboard arrows to change date < 31/12/100

----------
the control changes the date without any problem.
Then confirm that using the schedule you can change the date to values smaller than the year 100. But using the buttons of the control this does not work, because the limit year is 100.
But using the arrows on the keyboard, this limit does not exist and you can get to year 1.
Since Delphi sets the maximum date for 12/31/9999, then you can programmatically enter the minimum date for 01/01/01

In case of using Dataware components, table fields in database, you must observe which values are accepted in this case according to the database. but it will probably be the default limits used by the current programming languages.


----------  RAD Studio Delphi 10.3.1
unit System.DateUtils;

function IsValidDate(const AYear, AMonth, ADay: Word): Boolean;
begin
  Result := (AYear >= 1) and (AYear <= 9999) and
          (AMonth >= 1) and (AMonth <= 12) and
          (ADay >= 1) and (ADay <= DaysInAMonth(AYear, AMonth));
end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 redboy136 (redboy136) ★☆☆☆☆ -
盒子活跃会员
2019/5/6 22:26:57
2楼: 原理这样判断有效日期。谢谢, 学习了。
----------------------------------------------
你梦我圆
作者:
男 kylix2008 (kylix2008) ★☆☆☆☆ -
普通会员
2019/5/7 13:32:18
3楼: 谢谢1楼!

更正一下:
DValue:=StrToDataTime(fValue,0)有误,应为DValue:=StrToDataTimeDef(fValue,0);
DValue能正确转换为0030-01-30。


采用VarToDataTime可解决转换小日期问题。
try
  DValue:=StrToDataTimeDef(fValue,0);  //遇到0030-01-30会出错,默认值无效
except
  DValue:=VarToDataTime(fValue);
end;

但cxGrid中该字段滚动到可视范围内,显示该日期为空白, DEBUG模式下会弹出错误提示"Invalid argument",下拉该字段过滤框也会出该错误提示;cxCustomGridRecord.Values(i)实际上记录了值0030-01-30,VarToDataTime(fValue)能正确转换为日期0030-01-30,说明cxGrid是记录了该日期的(cxCustomGridRecord.Values(i)实际上有值0030-01-30),只是不能正常显示。

1楼解决了日期输入问题,怎么解决cxGrid不能正常显示小日期的问题呢?
----------------------------------------------
-
作者:
男 wj7927 (元素) ★☆☆☆☆ -
盒子活跃会员
2019/5/8 20:01:04
4楼: 字段类型用字符吧
----------------------------------------------
-
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2019/5/8 23:48:52
5楼: maybe help you, code to Cbuilder

DateEdit - How to change the MinDate property when changing a value in another DateEdit control

https://www.devexpress.com/Support/Center/Question/Details/T507738/dateedit-how-to-change-the-mindate-property-when-changing-a-value-in-another-dateedit
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2019/5/9 0:15:04
6楼: See that the value minimum to dates is defined on System.SysUtis.pas not in DevExpress units:

System.SysUtis.pas ---> where is defined the minimum value to TDateTime default - RAD Studio 10.3.1 Arch edition

line: 3039

const
  MinDateTime: TDateTime = -657434.0;      { 01/01/0100 12:00:00.000 AM }
  MaxDateTime: TDateTime =  2958465.99999; { 12/31/9999 11:59:59.999 PM }


https://www.devexpress.com/Support/Center/Question/Details/Q36648/tcxdbdateedit-the-evariantoverfolwerror-occurs

https://www.devexpress.com/Support/Center/Question/Details/Q333797/i-don-t-want-that-cxdatetime-raise-error-with-message-value-out-of-bounds
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2019/5/9 0:21:00
7楼: maybe, work with "date" in string format is not very good!
Because, you'll need always converting to TDate / TDateTime etc... to work in your system (calculate or tables in your database).

And, with one "wrong string" YOU will have one date wrong!

For this, the TDateTime use a type DOUBLE (numeric) to works/store the dates and times =   (left = days, right = time)

So, avoid any error math because, number is number, always!

you see?
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 kylix2008 (kylix2008) ★☆☆☆☆ -
普通会员
2019/5/10 14:42:35
8楼: 谢谢 emailx45。
字段类型是日期时间,不是字符类型。

再单独测试小日期:
var
  DValue:TDateTime;
  vv:variant;
begin
  DValue:= EncodeDate( 0030,01,30);
   //vv:= datetostr(DValue);  //当vv为string、variant类型均能正确运行
  vv:= VarFromDateTime(DValue);    
  DValue :=  StrToDateTimeDef(vv , 0);
end;

调试模式运行 VarFromDateTime(DValue)没弹出出错提示,但赋值给vv后,vv的值在调试器中显示为: Delphi exception EVariantInvalidArgError at $77A4F8A1
导致DValue :=  StrToDateTimeDef(vv , 0); 出错:invalid argument.
说明VarFromDateTime不支持小于0100年的日期,datetostr却支持。

继续跟踪到System.Variants.pas中的VarFromDateTime:
function VarFromDateTime(const DateTime: TDateTime): Variant;
begin
  _VarClear(TVarData(Result));
  TVarData(Result).VType := varDate;
  TVarData(Result).VDate := DateTime;
end;
运行VarFromDateTime不会弹出错误提示,但运行到end后调试显示Result值为Delphi exception EVariantInvalidArgError at $77A4F8A1
实际上是TVarData(Result).VDate := DateTime不能正常赋值的,TVarData(Result).VDate := DateTime又调用了system中的函数,是一段汇编代码。

Variant类型不支持小于0100年的日期?

测试环境:Windows 10、delphi 10.3.1
----------------------------------------------
-
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2019/5/11 4:38:52
9楼: http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.Variant

http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Internal_Data_Formats_(Delphi)#Variant_Types

http://docwiki.embarcadero.com/Libraries/Tokyo/en/System.Variants.TCustomVariantType


"The Variant type is used for variables that can change type at run time. Variants offer greater flexibility, but consume more memory than regular variables, and operations on them are slower than on statically bound types. Moreover, illicit operations on variants often result in run-time errors, where similar mistakes with regular variables would have been caught at compile time. You can also create custom variant types.

By default, Variant variables can hold values of any type except records, sets, static arrays, files, classes, class references, and pointers. In other words, variants can hold anything but structured types and pointers. They can hold interfaces, whose methods and properties can be accessed through them. They can hold dynamic arrays, and they can hold a special kind of static array called a variant array. Variants can mix with other variants and with Integer, Real, string, and Boolean values in expressions and assignments; the compiler automatically performs type conversions.

Variants that contain strings cannot be indexed.

You can define custom variants that extend the Variant type to hold arbitrary values. For example, you can define a Variant string type that allows indexing or that holds a particular class reference, record type, or static array. Custom Variant types are defined by creating descendants to the TCustomVariantType class.

On 32-bit platforms, a Variant occupies 16 bytes of memory. On 64-bit platforms, a Variant is a 24-byte record. A variant record consists of a type code and a value, or a pointer to a value, of the type specified by the type code. See Internal Representation of Variant Types. All variants are initialized on creation to the special value Unassigned. The special value Null indicates unknown or missing data."
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2019/5/11 4:44:49
10楼: read (all article) this about VARIANT  and TDATETIME type

http://docwiki.embarcadero.com/RADStudio/Rio/en/Variant_Types_(Delphi)

"Out-of-range assignments often result in the target variable getting the highest value in its range. Invalid variant operations, assignments or casts raise an Variants.EVariantError exception or an exception class descending from Variants.EVariantError.

Special conversion rules apply to the System.TDateTime type declared in the System unit. When a System.TDateTime is converted to any other type, it treated as a normal Double. When an integer, real, or Boolean is converted to a System.TDateTime, it is first converted to a Double, then read as a date-time value. When a string is converted to a System.TDateTime, it is interpreted as a date-time value using the regional settings. When an Unassigned value is converted to System.TDateTime, it is treated like the real or integer value 0. Converting a Null value to System.TDateTime raises an exception.

On the Win32 platform, if a variant references a COM interface, any attempt to convert it reads the object's default property and converts that value to the requested type. If the object has no default property, an exception is raised."

...
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2019/5/11 4:51:43
11楼: you see?

then, you need know "if" the "vv" (variant)  is not one value invalid. Then if yes, the conversion occurr but the value TDateTime will be the default value, for example. for that the error dont occur on the use, but the exception is catch by system when your app end, 

try use TRY/EXCEPT/END block for test

try
....
except
on e:exception {generic} do
showmessage( e.message );
end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 kylix2008 (kylix2008) ★☆☆☆☆ -
普通会员
2019/5/13 15:55:28
12楼: 之前的回复丢失了。
盒子出故障了?
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行80.07813毫秒 RSS