Deserialize joda time from string in grails?
Asked Answered
T

3

6

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?

Tse answered 22/11, 2013 at 21:14 Comment(4)
Have you tried to keep the field LocalTime and use Joda Time Grails Plugin? Also why do you use LocalTime instead of Duration for persisting duration?Bute
Did you try somethign like: <code> def str = "" as byte[]; def os = new ObjectInputStream(new ByteArrayInputStream(str)); LocalTime.Property.readObject(os); </code>Trenatrenail
No I haven't tried this out. Will try and see.Tse
I tried this out and got the following error: java.io.StreamCorruptedException: invalid stream header: 5C786163Tse
P
4

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.

Polyanthus answered 2/12, 2013 at 16:46 Comment(1)
From java, String data = "\\xaced0005737200176f72672e6...."; byte converted[] = PGbytea.toBytes(data.getBytes()); ByteArrayInputStream in = new ByteArrayInputStream(converted); System.out.println(new String(converted)) ;Polyanthus
J
1

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.

Jacquie answered 27/11, 2013 at 5:57 Comment(1)
Yeah later I did this only. Wanted to see if there was another way. Thanks anyways.Tse
T
1

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 ])
            }
        }
Tse answered 4/12, 2013 at 18:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.