Deserialize joda time from string in grails? - grails

I had a LocalTime field (using Joda Time) in Grails domain class.
Class WorkDone{
LocalTime duration
}
Now I have altered this field to String (with Text constraint) so that it can support duration larger than 24 hrs.
String duration
The problem is there is already some data in database. And I want to sanitize that data through database migrations in Grails. I am using Postgres which saves LocalTime as Bytea (binary data).
When I call WorkDone.duration it returns me a String of the form:
\xaced0005737200176f72672e6a6f64612e74696d652e4c6f63616c54696d65fffff44abbf29def0200024a000c694c6f63616c4d696c6c69734c000b694368726f6e6f6c6f677974001a4c6f72672f6a6f64612f74696d652f4368726f6e6f6c6f67793b78700000000000000000737200276f72672e6a6f64612e74696d652e6368726f6e6f2e49534f4368726f6e6f6c6f67792453747562a9c811667137502703000078707372001f6f72672e6a6f64612e74696d652e4461746554696d655a6f6e652453747562a62f019a7c321ae30300007870770500035554437878
How can I extract time from this string?

Your data is scaped in bytea Hex format, (starts with \x) take a look at PostgreSQL docs
http://www.postgresql.org/docs/current/static/datatype-binary.html
You have to unescape it before read as ObjectInputStream ang get the LocalTime object, unescape it and then try again as Raphael suggest.

You should have done a data-migration before changing your Data-type to String.
Here is what you should do.
1. Change the Data-type of the field back to LocalTime.
2. Create a new field with String Date.
3. Write a script that would get all date in LocalTime and convert it to String and save it in new field.
4. Once you have your data migrated, delete the old field and then rename your new field to duration.

I ended up doing the following -
grailsChange{
change{
sql.eachRow("Select id,duration from work_done"){
def wdId = it.id
def durationObj = (LocalTime)(new ObjectInputStream(new ByteArrayInputStream(it.duration))).readObject()
durationObj = durationObj.toString().substring(0,8)
WorkDone.executeUpdate("update WorkDone wd set wd.duration=:newDuration" +
"where wd.id=:wdId",
[newDuration:durationObj ,wdId:wdId ])
}
}

Related

thingsboard rulechain - filter script node to check if metadata timestamp is greater than server timestamp

I have created an asset variable with a timestamp attribute (dateTo) and would like to compare this to the current server time.
Ho do I get the server/system time of the Thingsboard. TBEL documentation states that "we have added Date class that you are able to use without the package name" so I should be able to get the server time with:
Date
Testing in the Test Filter Function doesn't error while using:
return Date > metadata.dateTo;
But does not assess correctly (changing the value around generates a False result either way).
Each metadata field has a string type, instead of integer as expected. So before comparison you have to convert metadata.dateTo to integer:
return Date.now() > +metadata.dateTo;

Getting an error while inserting data using stored procedure in mvc entity framework

I'm getting an error
converting data type nvarchar to datetime.
Where I did mistake?
var exec = db.Database.ExecuteSqlCommand("sp_InsertTicketChat #TicketId,
#FullName, #Description,
#LastCorrespondanceBy,#LastCorrespondanceOn",
new SqlParameter("#TicketId", TicketId),
new SqlParameter("#FullName", FullName),
new SqlParameter("#Description", Description),
new SqlParameter("#LastCorrespondanceBy", FullName),
new SqlParameter("#LastCorrespondanceOn",
DateTime.Now.ToString())
);
This is my stored procedure through which I want to insert data. What can I do ?
INSERT INTO tblTicketChat
(
TicketId,
FullName,
[Description],
LastCorrespondanceOn,
LastCorrespondanceBy
)
VALUES
(
#TicketId,
#FullName,
#Description,
GETDATE(),
#LastCorrespondanceBy)
Now I got the root cause of the issue you were facing.
Ideally, DateTime.Now.ToString() should have got converted to SQL Server Datetime data type when being assigned to the #LastCorrespondanceOn parameter of your stored procedure but it threw an exception.
The reason is date time format settings of your operating system.
The thing is when you perform DateTime.Now.ToString() in your C# language based client code it takes the default settings of date time format from your operating system. Look at the date time format currently set on my windows 10 box:
Due to this setting the code DateTime.Now.ToString() emits 27-07-2017 18:07:37. The output you're seeing is dd-MM-yyyy format.
Now this dd-MM-yyyy date format is not recognizable by SQL Server as per your default language settings.
SQL Server can recognize two date time formats when sent as string from client side
International date format yyyy-MM-dd also known as ISO 8601 .
Date format controlled by user login's dateformat setting. You can run dbcc useroptions command to see the value of setting. For me it is set to mdy
Due to this mismatch in the date time format being sent by your C# code (because of your operating system) and what SQL server can parse, you faced the issue.
When you did the conversion explicitly by date.ToString("yyyy-MM-dd"); you simply aligned it ISO 8601 international date time format supported by SQL Server so it started to work.
The default date time format (ISO 8601) of SQL Server is a configuration of the collation you are using currently which you can check in your SQL Server instance properties as shown below:
It is strongly recommended that you should always use SQL's date time format when passing it in string format as mentioned in this thread.
So you can solve your problem in three ways:
Change the default date format of your OS to align it to SQL Server (Not recommended). It will never be feasible on all client computers where your application runs.
Use custom date format while calling ToString method as you have done to align it to one of the formats supported by SQL Server. Best format is ISO 8601 format which you've used.
Don't convert it to string. Just pass the date time value as is.
var exec = db.Database.ExecuteSqlCommand("sp_InsertTicketChat #TicketId,
#FullName, #Description,
#LastCorrespondanceBy,#LastCorrespondanceOn",
new SqlParameter("#TicketId", TicketId),
new SqlParameter("#FullName", FullName),
new SqlParameter("#Description", Description),
new SqlParameter("#LastCorrespondanceBy", FullName),
new SqlParameter("#LastCorrespondanceOn",
DateTime.Now) //Don't call .ToString here
);
Approach # 3 is the best deal. More details here as to why you shouldn't use strings but the date time data type while dealing with SQL Server datetime columns.
I solve this issues by using MSSQL string formatted (dd-MM-yyyy) in my storedprocedure
I solved this issue by doing some changes.
DateTime date = DateTime.Now;
string strDateTime = date.ToString("yyyy-MM-dd");
var exec = db.Database.ExecuteSqlCommand("sp_InsertTicketChat #TicketId, #FullName, #Description, #LastCorrespondanceOn, #LastCorrespondanceBy",
new SqlParameter("#TicketId", TicketId),
new SqlParameter("#FullName", FullName),
new SqlParameter("#Description", Description),
new SqlParameter("#LastCorrespondanceBy", "raza"),
new SqlParameter("#LastCorrespondanceOn", strDateTime)
);

Rails string to DOB year

I'm currently storing strings formatted like "01/01/1989" (client side validation) for the bday field.
I want to parse out the year and store it as a variable, like this:
#bdayyear = current_user.bday.year
I want that to bring back "1989"
How would I go about doing that?
Just do using #strftime and ::strptime :
s = "01/01/1989"
current_user.bday.strptime(s, "%d/%m/%Y").strftime("%Y")
# => "1989"
Convert it into a DateTime object and you can call year on it
>> DateTime.parse("01/01/1989").year
=> 1989
If the format is always consistent the why not just use the string
"01/01/1989".slice(-4..-1)
"01/01/1989"[-4..-1]
Or
"01/01/1989".split(/\W/).pop
These will all return "1989" without converting it to a date

Delphi & Absolute database : Delete Query

Why is it that my query does not work ?
Form1.ABSQuery1.Close;
Form1.ABSQuery1.SQL.Clear;
Form1.ABSQuery1.SQL.Text:='DELETE FROM LOG WHERE status = ''YES'' and DATE BETWEEN :d1 and :d2';
Form1.ABSQuery1.Params.ParamByName('d1').Value :=cxDateEdit1.Date;
Form1.ABSQuery1.Params.ParamByName('d2').Value :=cxDateEdit2.Date;
Form1.ABSQuery1.ExecSQL;
Form1.ABSTable1.Refresh;
I get this error :
You should be using AsDateTime in your Params setting code.
Form1.ABSQuery1.SQL.Text:='DELETE FROM LOG WHERE status = ''YES'' and DATE BETWEEN :d1 and :d2';
Form1.ABSQuery1.Params.ParamByName('d1').AsDateTime :=cxDateEdit1.Date;
Form1.ABSQuery1.Params.ParamByName('d2').AsDateTime :=cxDateEdit2.Date;
Form1.ABSQuery1.ExecSQL;
Using Value converts the cxDateEdit1.Date to a generic string format for assignment, and that doesn't properly convert it to the YYYY-MM-DD format that most databases (including ABS) expect. Properly using AsDateTime allows the database driver/component to convert to the specific date format the DBMS uses.
Also, is your database field really named DATE? Date is usually a reserved word or function name in most DBMS, and if it is it usually needs to be quoted.
Form1.ABSQuery1.Params.ParamByName('d1').DataType := ftDateTime;
Form1.ABSQuery1.Params.ParamByName('d1').Value :=cxDateEdit1.Date;
You must explicitly specify the data type of the parameter to it had no such problem, and then convert to a string does not need to

Saving and Querying a Date in GORM Grails

I have a database table TableA, which has a column 'theDate' for which the datatype in the database is DATE.
When I save a java.util.Date to 'theDate' through GORM it appears to save just the date value when I look at the data in the table by just executing select * from TableA.
However, when I run a query such as:
select * from TableA where theDate = :myDate
No results are found, but if I run something like;
select * from TableA where theDate <= :myDate
I do get results.
So it's like the Time is relevant.
My question is how do I save a Date and query for a Date ignoring the Time completely and just matching on an exact Date only?
Thanks.
note: I have also tried using sql.Date and util.Calendar but to no success.
clearTime()
You can use clearTime() before saving and before comparing to zero out the time fields:
// zero the time when saving
new MyDomain(theDate: new Date().clearTime()).save()
// zero the target time before comparing
def now = new Date().clearTime()
MyDomain.findAll('SELECT * FROM MyDomain WHERE theDate = :myDate', [myDate: now])
joda-time plugin
An alternative would be to install the joda-time plugin and use the LocalDate type (which only holds date information, no times) instead of Date. For what it's worth, I don't think I've worked on a project with dates without using the Joda plugin. It's completely worth it.
If you have date saved without clearing you could retrieve it using range, as Jordan H. wrote but in more simple way.
def getResults(Date date) {
def from = date.clearTime()
def to = from + 1
def results = MyDomain.findAll("from MyDomain where dateCreated between :start and :stop" ,[start:from,stop:to])
}
Your question may be a duplicate. See Convert datetime in to date. But if anyone has more recent information, that would be great.
If that doesn't help, you can hack it the way I might, with a BETWEEN restriction, e.g.
def today = new Date()
def ymdFmt = new java.text.SimpleDateFormat("yyyy-MM-dd")
def dateYmd = ymdFmt.format(today)
def dateTimeFormat = new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
def startDate = dateTimeFormat.parse("${dateYmd} 00:00:00");
def endDate = dateTimeFormat.parse("${dateYmd} 23:59:59");
MyDomain.findAll("from MyDomain where dateCreated between ? and ?", [startDate, endDate])
It's definitely not pretty, but it may get you where you're going.
I figured it out.
I used DateGroovyMethods.clearTime to clear the time value before saving.
You can use the DB type date not datetime , in the filed type

Resources