WSO2 DSS appends timezone information to mysql date result - mysql

So I'm trying to use dates with mysql on the wso2 dss.
Simple code
<query id="testDates" useConfig="PORTFOLIOS_DS">
<sql>
SELECT DATE(date) AS date FROM dateTest
</sql>
<result element="jsonObject" rowName="jsonArray">
<element column="date" name="testDate" xsdType="date"/>
</result>
</query>
So it returns "2015-03-10-04:00" which isn't considered a valid date my many libraries (momentJS in particular) and to be fair it is a strange format, why do I care about timezone without the time.
Does anyone know why it is appending the timezone, how can I prevent the appending of timezone to dates but leave it on datetimes?

I was able to reproduce this issue with DSS 3.5.0 version. So I have already created a public JIRA ticket [1]. and once this is fixed I will notify you.
In the meantime as a workaround, I would like to suggest to use an XSLT transformation to trip off timezone information. For more information about how to use XSLT inside the DSS server please refer [2]
[1]. https://wso2.org/jira/browse/DS-1191
[2]. https://docs.wso2.com/display/DSS350/XSLT+Transformation+Sample

Related

MySql Timezone JDBC issue

I am trying to insert a date value in MySql table name person and column name regdate with data type = datetime. I am setting a value e.g. '2019-08-21 20:25:20' but after saving +5:30 hours get added and value which gets stored is '2019-08-22 03:55:20'. Generating the date value using below Java code
Timestamp curDate = Timestamp.valueOf(Instant.now().atZone(ZoneId.of("Asia/Kolkata")).toLocalDateTime());
and then using .setTimestamp(1, curdate); in INSERT query.
I have checked that the timezone of MySql is set to IST (GMT+0530). App Server timezone is also set to IST. But I am not able to understand why +5:30 hours are getting added even if I explictly setting the date value.
I have tried setting timezone in connection string as ?serverTimezone=Asia/Kolkata but didn't work.
But if I run the same code using my local machine connecting same MySql instance, I get no problem and same value gets stored without addition of 5:30 hours. I checked App Server timezone and it is IST.
MySql version - 5.7.17-log
mysql-connector-java - 8.0.15
Am I missing something?
You have a few problems here.
Avoid legacy date-time classes
First of all, you are mixing the terrible legacy date-time classes (java.sql.Timestamp) with the modern java.time classes. Don’t. Use only classes from the java.time packages.
LocalDateTime cannot represent a moment
You are using LocalDateTime to track a moment, which it cannot. By definition, that class does not represent a point on the time line. That class has a date and a time-of-day but intentionally lacks the context of a time zone or offset-from-UTC. Calling toLocalDateTime strips away vital information about zone/offset.
Tools lie
You are likely getting confused by the well-intentioned but unfortunate behavior of many tools to dynamically apply a time zone while generating text to represent the date-time value retrieved from the database. You can avoid this by using Java & JDBC to get the pure unadulterated value from the database.
TIMESTAMP WITH TIME ZONE
You failed to disclose the exact data type of your column in your database. If you are trying to track a moment, use a data type akin to the SQL-standard type TIMESTAMP WITH TIME ZONE. In MySQL 8 that would, apparently, be the TIMESTAMP type according to this doc. (I am a Postgres guy, not a MySQL user.)
In JDBC 4.2 and later, we can exchange java.time objects with the database. So no need to over touch java.sql.Timestamp again.
Unfortunately, the JDBC spec oddly chose to not require support for Instant (a moment in UTC) nor forZonedDateTime(a moment as seen in some particular time zone). The spec does require support for [OffsetDateTime`]2.
Tip: Learn to work in UTC for the most part. Adjust into a time zone only when required by business logic or for presentation to the user.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ; // Capture current moment in UTC.
Write to the database via a prepared statement.
myPreparedStatement.setObject( … , odt ) ;
Retrieval.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
View that moment through the wall-clock time used by the people of some particular region (a time zone).
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

MySQL/Hibernate: getting value +1H on insert type Time

I'm working on a java web project that uses:
Hibernate 5.2.2/JPA 2.0+ MySQL5InnoDBDialect
MySQL 5.6.15-innoDB (on EasyPHP/PHPMyAdmin) + JDBC connector 6.0.4
Joda time API 2.9.4 + Fasterxml jackson API 2.8.3
I'm facing a problem on inserting Time data on database. everytime i put a row, i get a +1H value on time column!
Attribute on Java:
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="HH:mm")
#Column(name = "RES_DUREE", nullable = false)
#Temporal(TemporalType.TIME) private Date resDuree;
Attribute on SQL:
RES_DUREE TIME NOT NULL;
EDIT (After Adrian Shum's Comment):
Connection line:
jdbc.url =
jdbc:mysql://localhost:3306/mydb?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
I do use UTC but it still 1H+ .
Any suggestion will help, thanks.
Normally it is caused by server and DB time zone mismatch.
In brief, java.util.Date does not contain Timezone information. Conceptually you can treat it as simply representing Date + Time (similar to what JODA/JSR310 LocalDateTime is doing). Therefore if your app server is UTC+10, and your DB is UTC+2, when you save a date of "2016-10-13 10:11:12", although your app server is treating it as "2016-10-13 10:11:12 +10:00", it is simply passing "2016-10-13 10:11:12" to DB. Given DB is UTC+2, it is thinking the time actually means "2016-10-13 10:11:12 +02:00". Situation become more messy if your JDBC connection is claimed to be "UTC+10", most DB is going to "smartly" translate "2016-10-13 10:11:12 +02:00" to "2016-10-13 18:11:12 +10:00" which caused weird time stored and retrieved.
You may diagnose by tracing the SQL (and the actual value used) for corresponding inserts and select. You should see discrepancies between the values, vs the value stored in table. Such tracing can be done by misc way, e.g.
Older version of Hibernate can show the parameter used in prepared statement by turning on proper logger
You may use tools like JdbcDsLog (Disclaimer: I am maintainer for a fork of JbdcDsLog at http://github.com/adrianshum/jdbcdslog)
There is probably tools in DBMS side to trace incoming queries.
Best way to solve is to make sure everything is in the same timezone, and the most rational choice for timezone is UTC.

Grails default timezone nature while building API

I am using grails 2.4.4 for building a restful API. I am having a lot of trouble figuring out grails default time-zone settings.
The premise of the problem is I am using default grails setting without using and dateBinders in config.groovy and the timezone of my both mysql and application server is in NPT.
So I am posting a json something like
{"clusterStartTime":"2015-10-15T17:45:00Z"}
Now this is a ISO 8601 format. So how can this date format represent my timezone so grails can interpret it ??
In database it is being saved as 2015-10-15 17:45:00.
But when I get this resource I am getting :
{"clusterStartTime": "2015-10-15T12:00:00Z"}
So I am getting a time with offset of 5:45 which is NPT offset. So how is grails doing all of this ??
So in production I have a server in NPT timezone so how can I save all my dates in UTC timezone and spit out dates in UTC timezone using grails only without setting Java enviroment variables ??
In your bootstrap.groovy set the timezone like this:
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Katmandu"))
NTP is not supported directly. To get a list of supported timezones see the output of TimeZone.getAvailableIDs().
In order to interpret correctly any ISO 8601 date you have to use a good parser. The one provided by javax.xml.bind.DatatypeConverter should be good enough. The method parseDateTime expects a lexicalXSDDateTime, which must be ISO 6801 compliant.
Therefore try this:
def cal = javax.xml.bind.DatatypeConverter.parseDateTime('2015-10-15T17:45:00Z')
def d = cal.getTime()
def t1 = new TestClass(myDate: d).save(failOnError:true)
println t1.myDate //Thu Oct 15 17:45:00 NPT 2015
The date gets saved on the database (e.g. in a DATETIME field) considering the time zone you defined, so it should be correct when you retrieve it.

dbdeploy error with --// in deploy-file

I am generating deployment-files for my mysql-database with phing and dbdeploy.
The output of a dbdeploy-file that is generated looks like the following:
-- Fragment begins: 8 --
INSERT INTO changelog
(change_number, delta_set, start_dt, applied_by, description) VALUES (8, 'Main', NOW(), 'dbdeploy', '8-add_tracking_code.sql');
--//
ALTER TABLE `order` ADD `tracking_code` VARCHAR(255) NOT NULL;
UPDATE changelog
SET complete_dt = NOW()
WHERE change_number = 8
AND delta_set = 'Main';
-- Fragment ends: 8 --
The Problem is the --// before the ALTER Statement. The database got an error with it. If I remove the --// the hole file ist correct.
Here is a piece of my phing build-script so that you can see how I am generating the .sql-File with dbdeploy:
<target name="dbdeploy-migrate-all">
<!-- load the dbdeploy task -->
<taskdef name="dbdeploy" classname="phing.tasks.ext.dbdeploy.DbDeployTask"/>
<echo message="Loading deltas from ${build.dbdeploy.alters_dir}" />
<property name="build.dbdeploy.deployfile" value="${build.dbdeploy.deploy_dir}/deploy-${DSTAMP}${TSTAMP}.sql" />
<property name="build.dbdeploy.undofile" value="${build.dbdeploy.undo_dir}/undo-${DSTAMP}${TSTAMP}.sql" />
<!-- generate the deployment scripts -->
<dbdeploy
url="mysql:host=${db.host};dbname=${db.name}"
userid="${db.user}"
password="${db.pass}"
dir="${build.dbdeploy.alters_dir}"
outputfile="${build.dbdeploy.deployfile}"
undooutputfile="${build.dbdeploy.undofile}" />
<!-- execute the SQL - Use mysql command line to avoid trouble with large files or many statements and PDO -->
<property name="mysql.command" value="${progs.mysql} -h${db.host} -u${db.user} -p${db.pass} ${db.name} < ${build.dbdeploy.deployfile}" />
<echo message="Executing command: ${mysql.command}" />
<exec
command="${mysql.command}"
dir="${base.path}"
checkreturn="true" />
</target>
Why does dbdeploy generate a corrupt file?
Thans for your help!
A long time has passed since this question was asked, however I ran into the same problem and have managed to work out where Niels is coming from on this one.
I think we both ran into the problem because we both followed the popular tutorial on phing and dbdeploy by Dave Marshall here: http://davedevelopment.co.uk/2008/04/14/how-to-simple-database-migrations-with-phing-and-dbdeploy.html
In his example sql delat file he includes --// at the top which, if replaced with a comment in /* .... */ format instead, avoids this problem!
So I would say this is a bug in the tutorial, which is 8 years old now. Dave notes at the top of the tutorial that about 4 years ago he moved onto a different method, so it is kind of understandable that there is now a bug in the tutorial! I will submit a comment requesting an update though, because his page is a top ranking search result when searching for the topic so it would be good if we can save people the same problem we've had!
It is a shame phing didn't give a more detailed error report in the form of the SQL exception - there's an idea for a contribution to the dbdeploy script!

JPA hibernate date between query issue

In my application am using JPA entity manager to persist data/fetch data.
em.executeQuery("select * from file_calender_mapping where start_date between :start and :end");
em.setParameter("start",startDate)//startDate is an date object
em.setParameter("end",endDate)//endDate is an date object
List fmlist=em.execute();
The proble is just like this,
"select * from file_calender_mapping where start_date between start and end"
when am passing some date as start= "2011-08-03 05:08:00",and end="2011-08-04 06:08:00"
then the mysql return one row having the start time ="2011-08-03 05:30:00",its good,But
when my application executing such query it dose not returning any row.Actually what i have seen that my application returning value for two different date,but not for same date different time,thats the main problem.
One another thing is my "start" field for Table "file_calender_mapping" datatype is "timestamp".
So what i was thinking that ther may be some problem on JPA/Hibernate
You can try to specify the exact types of parameters as follows:
em.setParameter("start", startDate, TemporalType.TIMESTAMP);
em.setParameter("end",endDate, TemporalType.TIMESTAMP);
I have the strong feeling that you're confusing EntityManager.createQuery() with EntityManager.createNativeQuery() and you're somehow capturing all the exceptions, which somehow makes you don't receive anything back.
I'm assuming that, because I don't think you have a class named file_calender_mapping.
edit
The documentation will explain it better than I do, but a JPA QL query is transformed to the navite sql of the DB using the mapping, while a native query is send as it's to the DB.
Again, I suggest you to read the documentation, it's quite useful.