XSuperObject: what's wrong with this date field? - json

unit fmainForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses XSuperObject;
procedure TForm1.FormCreate(Sender: TObject);
var fileContents : string;
job: ISuperObject;
LDate: TDate;
LValue: string;
LFormat: TFormatSettings;
LDouble: Double;
begin
fileContents := '{' +
' "Id": "POS-1",' +
' "Employer": {' +
' "Name": {' +
' "Normalized": "Acme"' +
' }' +
' },' +
' "IsSelfEmployed": false,' +
' "IsCurrent": true,' +
' "StartDate": {' +
' "Date": "2020-03-01",' +
' },' +
' "EndDate": {' +
' "Date": "2021-06-08",' +
' },' +
'}';
job := SO(fileContents);
if Assigned(job['Id']) then
Memo1.Lines.Add('Job Id = ' + job['Id'].AsString);
if Assigned(job['Employer.Name.Normalized']) then
Memo1.Lines.Add('Employer name = ' + job['Employer.Name.Normalized'].AsString);
if Assigned(job['StartDate.Date']) then
Memo1.Lines.Add('Start date = ' + job['StartDate.Date'].AsString);
if Assigned(job['EndDate.Date']) then
Memo1.Lines.Add('End date = ' + job['EndDate.Date'].AsString);
end;
end.
Most of it works. E.g job['Id'].AsString evaluates to 'POS-10', etc.
But job['StartDate.Date'].AsString evaluates to '43891' and EndDate to '44355'. What am I doing wrong?
That's
Job Id = POS-1
Employer name = Acme
Start date = 43891
End date = 44355

Looking at XSuperObject's source code, it turns out that by default, XSuperObject will process a String field as a Date/Time field if the string value resembles a valid date/time string (which it does, in this situation).
In Delphi, a TDate(Time) is implemented as a Double. You are seeing XSuperObject parsing your JSON's StartDate and EndDate fields as if they were TDate values, not plain String values. And then, when you call .AsString on those fields, you are getting back the numeric representation of those TDate values, not the original String data.
You can disable this behavior, however the SO() function does not allow you to do so. You will have to construct a TSuperObject object directly, so you can pass False to its CheckDate parameter (which is True by default), eg:
//job := SO(fileContents);
job := TSuperObject.Create(fileContents, False);

TDate is just a normal Double type.
When you do AsString, in reality you convert the double value as string.
You will see that your field contain a TDate and not a string by doing :
LType := job['StartDate.Date'].DataType; // dtDate
If you want to get the date value as string, you need to use DateToStr :
if Assigned(job['StartDate.Date']) and (job['StartDate.Date'].DataType = dtDate) then
begin
Memo1.Lines.Add('Start date = ' + DateToStr(job['StartDate.Date'].AsDate));
end;

Related

Is there an "integer" version of "quotedstr" to be used in Delphi 2010

QuotedStr() is used to enter string values into an SQL query in Delphi 2010, and I'm wondering if such a thing exists for integer values. For example:
qryRes.Close;
qryRes.SQL.Text := 'Insert INTO Reservaatdetails (MaxcusperRes)VALUES(' + QuotedStr(ownobjek.getMaks) + ' ) ';
qryRes.ExecSQL;

Insert date to mysql with node

I'm currently trying to get the current date and try to save on my database but the only thing i get on my date column is 1982 , really strange ? Here is my code for the date and the mysql insertion :
DATE :
var dateTime = require('node-datetime')
var dt = dateTime.create();
var formatted = dt.format('Y-m-d');
console.log(formatted);
Mysql insertion :
pool.query(
'INSERT INTO jbets SET user = ' + pool.escape(tradingRequests[offer.id]['user']) +
', assetids = ' + pool.escape(assetidsSS) +
', value = ' + pool.escape(totalPrice) +
', minTicket = ' + pool.escape(minTicket) +
', maxTicket = ' + pool.escape(maxTicket) +
', total = ' + pool.escape(totalSkins) +
', jid = ' + pool.escape(jackpotRound) +
', token = ' + pool.escape(offer.id) +
',date =' + formatted
)
You should really be using placeholders.
You shouldn't be trying to convert the date object to that string format before inserting into a date field in the DB. The proper format would be YYYY-mm-dd HH:ii:ss, however you could let your MySQL library handle the conversion for you.
I suggest reading the Escaping Query Values section of the MySQL JS library documentation.
Try something like this:
pool.query('INSERT INTO jbets SET user = ?, assetids = ?, value = ?, ' +
'minTicket = ?, maxTicket = ?, total = ?, jid = ?, token = ?, date = ?',
[tradingRequests[offer.id]['user'], assetidsSS, totalPrice,
minTicket, maxTicket, totalSkins, jackpotRound, offer.id, dt]);
Use this code :
pool.query('INSERT INTO jbets (user, assetids, value, minTicket, maxTicket, total, jid, token, date) VALUES(pool.escape(tradingRequests[offer.id]['user']), pool.escape(assetidsSS), pool.escape(totalPrice), pool.escape(minTicket), pool.escape(maxTicket), pool.escape(totalSkins), pool.escape(jackpotRound), pool.escape(offer.id), NOW()));
Thanks for responding the problem was from my db i was need to change the ty to varchar

sql "The data types varbinary and varchar are incompatible in the add operator."

update UserData set strItem = cast( substring(strItem, 1, #i) + cast(cast(#Cdwid as varchar(4)) + #Cdur + #Cstack as varchar(8)) + substring(strItem, #i+8, 401-#i) as binary(400)) where strUserID = #strUserID``
and error
The data types varbinary and varchar are incompatible in the add operator.
What am I doing wrong?
thanks...
EDIT ---------------------
thanks for your ansver, I solved this problem, i dont convert strItem (binary) to string (varchar).
new code :
update UserData set strItem = cast( substring(cast(strItem as varchar(4)), 1, #i) + cast(cast(#Cdwid as varchar(4)) + #Cdur + #Cstack as varchar(8)) + substring(cast(strItem as varchar(4)), #i+8, 401-#i) as binary(400)) where strUserID = #strUserID

Application uses a value of the wrong type for the current operation

I have a Delphi XE app connecting by ADO to an Access MDB file. The following code gives the error "Application uses a value of the wrong type for the current operation" on opening the query. The field RegDate is an Access Date/Time type. dteTo and dteFrom are TDateTimePicker components. I tried using an ftDate parameter type too but get the same error. What is the trick to get date parameters working with ADO?
with DM.Query2 do
begin
Close;
ParamCheck := True;
SQL.Text:= 'SELECT Sum((ItemCost * Quantity) + GST + PST + Handling) As Total1'+
' FROM Software S INNER JOIN Items I ON (S.SoftwareID = I.Invoice)'+
' WHERE RegDate BETWEEN :Date1 AND :Date2';
if chkPaid.Checked then
SQL.Text:= SQL.Text+' AND S.Paid = True';
Parameters.ParamByName('Date1').Value:= dteFrom.Date;
Parameters.ParamByName('Date1').DataType := ftDateTime;
Parameters.ParamByName('Date2').Value:= dteTo.Date;
Parameters.ParamByName('Date2').DataType := ftDateTime;
Open;
lblYTD.Caption:= 'YTD: '+FieldByName('Total1').AsString;
Close;
end;
Using the Orders table from DBDemos.mdb that ships with Delphi, with the Access 15 (Microsoft.ACE.OLEDB.15.0) driver, the following works fine. Other than the ConnectionString, everything is done in the code; there are no pre-defined parameters or altered properties on the ADOQuery.
procedure TForm1.Button1Click(Sender: TObject);
begin
ADOQuery1.SQL.Text := 'Select OrderNo, CustNo, SaleDate, ShipDate ' +
'From Orders ' +
'Where SaleDate between :Date1 and :Date2 ' +
'Order By CustNo, OrderNo';
// Only for demonstration purposes
DateTimePicker1.Date := EncodeDate(1988, 8, 1);
DateTimePicker2.Date := EncodeDate(1988, 8, 31);
ADOQuery1.Parameters.ParamByName('Date1').Value := DateTimePicker1.DateTime;
ADOQuery1.Parameters.ParamByName('Date2').Value := DateTimePicker2.DateTime;
ADOQuery1.Open;
ShowMessage(Format('Found %d records', [ADOQuery1.RecordCount]));
ADOQuery1.Close;
end;

SQL Server separate: FirstName, MiddleName and LastName

Good day!
I get a "Varchar" which is the full name of a client, and need to split this "varchar" as:
"FirstName MidleName MiddleNameTwo LastName "
Need to enter the "FirstName" on "Col1"
Need to enter the "MiddleName, MiddleNameTwo in" col2 "
Need to enter the "LastName" in "Col3"
Thanks for your help!
You Should use subqueries for this task
INSERT INTO names(firstname, middlename, lastname)
SELECT substringfunctionofyours(name), substringfunctionofyours(name),
substringfunctionofyours(name) FROM namefield
keep in mind this is just a dummy query it won't work if you use it like this
Can you change the input method to 4 separate fields ?
If you can't, then implement a specific delimeter between the different parts of the string ?
In cases where the last name is built with 2 words, there is no deterministic way of processing the string if the delimeter is [space] or any other character like '-' or ' which are common in names.
Using a delimeter like '|' :
Declare #FullName varchar(100) = 'FirstName|MidleName|MiddleNameTwo|LastName'
Print 'FirstName = ' + Substring(#FullName,1,charindex('|',#FullName)-1)
SELECT #FullName = Substring(#FullName,charindex('|',#FullName)+1,len(#fullName))
Print 'MiddleName1 = ' + Substring(#FullName,1,charindex('|',#FullName)-1)
SELECT #FullName = Substring(#FullName,charindex('|',#FullName)+1,len(#fullName))
Print 'MiddleName2 = ' + Substring(#FullName,1,charindex('|',#FullName)-1)
SELECT #FullName = Substring(#FullName,charindex('|',#FullName)+1,len(#fullName))
Print 'LastName = ' + #FullName
This will also work if you don't have one of the parts, as long as you maintain the structure.
Declare #FullName varchar(100) = 'FirstName|MidleName||LastName'
Print 'FirstName = ' + Substring(#FullName,1,charindex('|',#FullName)-1)
SELECT #FullName = Substring(#FullName,charindex('|',#FullName)+1,len(#fullName))
Print 'MiddleName1 = ' + Substring(#FullName,1,charindex('|',#FullName)-1)
SELECT #FullName = Substring(#FullName,charindex('|',#FullName)+1,len(#fullName))
Print 'MiddleName2 = ' + Substring(#FullName,1,charindex('|',#FullName)-1)
SELECT #FullName = Substring(#FullName,charindex('|',#FullName)+1,len(#fullName))
Print 'LastName = ' + #FullName
Let say you have a name like this "ABC DEF GHI"
now you want First Name, Middle Name and last Name From this string.
Here We Go
Select
Substring(Cast('ABC DEF GHI' as nvarchar),0,charindex(' ',Cast('ABC DEF GHI' as nvarchar))) as Col1,
Substring(Cast('ABC DEF GHI' as nvarchar),charindex(' ',Cast('ABC DEF GHI' as nvarchar)),4)as Col2,
Substring(Cast('ABC DEF GHI' as nvarchar),8,charindex(' ',Cast('ABC DEF GHI' as nvarchar)))as Col3
Note: This is MSSQL SERVER Query and Substring Function is Built in in MSSQL SERVER