Grails default timezone nature while building API - mysql

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.

Related

how to find out the timezone of given time from mysql db in node js

I am quite new to Node js.
I want to know what timezone the given datetime value, which comes from mysql db, it is .
For example
const conference = await mysqlHelper.query(conferenceSql);
// select query
const time = conference[0].created_datetime
// I wonder how to get the timezone from this time variable here.
console.log(time)
// console.log returns '2021-02-23T01:30:00.000Z' to the terminal
mysql value type: datetime
I know I could directly look up the db table instead of figuring out in node js. However, this is a required task for validation in my server.
Thanks a lot !!
Mysql datetime does not store time zone information.
2021-02-23T01:30:00.000Z is displayed in an ISO 8601 format, being in UTC.

how timestamp's timezone works in a database and/or Laravel

I have a question regarding timezone for timestamps.
How the timezone in app.php is used? I realized that the behavior is different if I create a timestamp using Carbon or if I query the value (timestamp) from the DB.
Note: My MySQL use system's timezone which is GMT+8 or Asia/Kuala_Lumpur.
Example #1
Set timezone="UTC" in app.php
Create a Carbon instance
>>> new Carbon\Carbon;
=> Carbon\Carbon #1572404830 {#3496
date: 2019-10-30 03:07:10.625282 UTC (+00:00),
}
>>>
Example #2
Set timezone="Asia/Kuala_Lumpur" in app.php
Create a Carbon instance
>>> new Carbon\Carbon;
=> Carbon\Carbon #1572404816 {#3520
date: 2019-10-30 11:06:56.316851 Asia/Kuala_Lumpur (+08:00),
}
For example #1 and #2, this is for me, expected. You got different value based on the timezone. Things got a little weirder (at least for me), when we query a timestamp from the DB.
Example #3
Set timezone="UTC" in app.php
Query from DB
>>> RefCyberCity::whereDataSource('ccms')->take(1)->first()->updated_at
=> Illuminate\Support\Carbon #1572083605 {#3531
date: 2019-10-26 09:53:25.0 UTC (+00:00),
}
Example #4
Set timezone="Asia/Kuala_Lumpur" in app.php
Query from DB
>>> RefCyberCity::whereDataSource('ccms')->take(1)->first()->updated_at
[!] Aliasing 'RefCyberCity' to 'App\RefCyberCity' for this Tinker session.
=> Illuminate\Support\Carbon #1572054805 {#3491
date: 2019-10-26 09:53:25.0 Asia/Kuala_Lumpur (+08:00),
}
We can see that both output 2019-10-26 09:53:25.0 but the timezone is different.
Dates coming from the database are effectively a string, and although MySQL has its own timezone information, that is not reflected in a date string without a timezone in it.
The Laravel DB drivers are asuming that it was written as the timezone that’s set in the app config. If you were to change your timezone mid-project, this would throw out all your dates.
My personal advice on timezones is to keep everything as UTC on your application and servers, then only change the timezone at the last possible moment (such as in the view), based on the user’s preference. This also allows you to output the UTC timestamp and have JavaScript update it to the user’s locale. Timezones are very hard, and if your country has daylight savings, timezones become even more confusing as Europe/London for example shifts timezone depending on the year.

Compare two datetime in angular (one is fetch from mysql database and one is node server)

I want to compare datetime in angular.
for example i have two following date
Registation Start Date : 2019-08-26 12:24:21 from mysql database
I am using Node server as backend
Current Date from node server
serverDate :new Date();
I have converted above serverDate to mysql format using following code
newServerDate : new Date().toISOString().slice(0, 19).replace('T', ' ')
i have send newServerDate to angular which i have used as front end. In angular i have compare above two date as follows
var DateFormMysql = 2019-08-26 12:24:21
var DateFromNode = 2019-08-26 12:24:21
if(DateFromNode <= DateFormMysql ){
console.log('in if');
}
I am stuck on above code, i am not able to compare two datetime variables
P.S : i want to mention here the datetime i get from node server is not correct
For example when i was writting this question,i get following datetime when i console new Date() in angular
Tue Aug 27 2019 13:27:28 GMT+0530 (India Standard Time)
when i console same new Date() in node server i get following result
2019-08-27T08:00:31.301Z
Dont know where i am getting wrong
I would recommend date-fns because you can import only those functions that you need. Maybe moment.js ha change but it used be very big and you needed to import everything
I'd advise you to use Moment.js : https://momentjs.com/
The package on npm is here : https://www.npmjs.com/package/moment
It's a really powerful library that allows you to compare dates.
This way you could do :
import * as moment from 'moment
moment(DateFormMysql).isAfter(moment(DateFromNode)) //=> true/false

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 ) ;

node js Sequelize with MySQL date formate issue

I developed node js services with Sequelize with MySQL Everything working good. I am storing data in DB with date and time with service but if I get the same data with service, node js automatically converting time (a wrong format which is not in the database), I want same time which is present in the database. to solve this issue I set the timezone in services and in the database but none of them is working. can anyone provide me with the solution.
suggestion
you could include time format function in mysql
for example
SELECT TIME_FORMAT("19:30:10", "%H %i %s");
result
TIME_FORMAT("19:30:10", "%H %i %s")
19 30 10
ref
That's not the issue of node js , Sequelize by default gives the time in UTC , so that date time will be correct
Check : Just compare your date time with UTC , and check is that you are getting.
Solution : So what you can do is , just convert returned date and time to your timezone and you are good to go.
And that's a good practice if you are using UTC everywhere , you can get benefits when you are getting / showing in many countries.