In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly explains "how to troubleshoot the inconsistency between the output date format of the interface caused by JDK and the expected time", interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to troubleshoot the inconsistency between the output date format of the interface caused by JDK and the expected time.
Bug description
The problem arises from the fact that a colleague added an interface to count the details of a user's birthday in the project, in which a user's birthday date in the database is "1988-07-29", but the user's birthday date is "1988-07-28" through the rest interface.
Environment description
Before you start bug troubleshooting, describe the project environment:
System: centos 7.5
JDK:1.8.0_171
Technology stack: spring boot, Jackson, Druid, mybatis, oracle.
Bug troubleshooting starts with the data layer, first querying the database time and time zone. SQL > SELECT SYSTIMESTAMP, SESSIONTIMEZONE FROM DUAL SYSTIMESTAMP SESSIONTIMEZONE -17-JUL-19 02.20.06.687149 PM + 08:00 + 08:00SQL >
View operating system time zone
[test@test ~] $date-RWed, 17 Jul 2019 16:48:32 + 0800 [test@test ~] $cat / etc/timezoneAsia/Shanghai
View the java process time zone
[test@test ~] $jinfo 7490 | grep user.timezoneuser.timezone = Asia/Shanghai
We can see that the time zone used by our operating system is the same as that used by the java process, both East Zone 8.
Use debug to continue to look up the mybatis and JDBC layers
It is seen that the jdbcType type of the problem field mapper mapping field is jdbcType= "TIMESTAMP", and the corresponding processing class in the type handling registration class TypeHandlerRegistry.java in mybatis is DateTypeHandler.java.
This.register ((JdbcType) JdbcType.TIMESTAMP, (TypeHandler) (new DateTypeHandler ()
Take a closer look at the DateTypeHandler.java class:
/ Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler) / / package org.apache.ibatis.type;import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Timestimport java.util.Date;public class DateTypeHandler extends BaseTypeHandler {public DateTypeHandler () {} public void setNonNullParameter (PreparedStatement ps, int I, Date parameter, JdbcType jdbcType) throws SQLException {ps.setTimestamp (I, new Timestamp (parameter.getTime () } public Date getNullableResult (ResultSet rs, String columnName) throws SQLException {Timestamp sqlTimestamp = rs.getTimestamp (columnName); return sqlTimestamp! = null? New Date (sqlTimestamp.getTime ()): null;} public Date getNullableResult (ResultSet rs, int columnIndex) throws SQLException {Timestamp sqlTimestamp = rs.getTimestamp (columnIndex); return sqlTimestamp! = null? New Date (sqlTimestamp.getTime ()): null;} public Date getNullableResult (CallableStatement cs, int columnIndex) throws SQLException {Timestamp sqlTimestamp = cs.getTimestamp (columnIndex); return sqlTimestamp! = null? New Date (sqlTimestamp.getTime ()): null;}}
Because the data source used is Druid, where ResultSet in the getNullableResult (ResultSet rs, String columnName) method parameter uses the getTimestamp (String columnLabel) of DruidPooledResultSet.java, gets the value through the column name and converts it to a value of type Date.
From the figure above, debug shows that Timestamp is a class in JDK, that is, what you see here is the time and time zone used by JDK. You can see that the time zone used by JDK is also East Zone 8, but it looks a little different from 1 and 3. First of all, there is such a time when there is a daylightSaving at UTC/GMT+0900,3, which translates to exactly 1 hour. This value is known as daylight saving time through a google search.
Common time concept UTC,GMT,CST,DST
UTC coordinated Universal time (English: Coordinated Universal Time, French: Temps Universel Coordonn é, UTC) is the most important world time standard, which is based on atomic time seconds and is as close to Greenwich mean time as possible. The Republic of China uses CNS 7648's "data element and Exchange format-Information Exchange-date and time representation" (similar to ISO 8601) to call it Universal coordinated time. The people's Republic of China adopts the national standard GB/T 7408-2005 "data elements and Exchange format Information Exchange date and time representation", which is also called coordinated Universal time in the people's Republic of China. (excerpt from: https://zh.wikipedia.org/wiki/%E5%8D%8F%E8%B0%83%E4%B8%96%E7%95%8C%E6%97%B6)
GMT Greenwich mean time (English: Greenwich Mean Time,GMT) refers to the local mean solar time at the Royal Greenwich Observatory on the outskirts of London, England, because the prime meridian is defined as the longitude that passes there. (excerpt from: https://zh.wikipedia.org/wiki/%E6%A0%BC%E6%9E%97%E5%B0%BC%E6%B2%BB%E6%A8%99%E6%BA%96%E6%99%82%E9%96%93)
CST Beijing time, also known as China Standard time, is the standard time of Chinese mainland, which is eight hours faster than UTC (UTC+8) and the same as the standard time in Hong Kong, Macau, Taipei, Kuala Lumpur and Singapore.
Beijing time is not the local mean solar time in Beijing (longitude 116.4 °E), but the local mean solar time in longitude 120 °E. the difference between the two is about 14.5 minutes. Beijing time is accurately compared and calculated by nine cesium atomic clocks and two hydrogen atomic clocks in the National time Service Center of the Chinese Academy of Sciences in Lintong, Shaanxi Province. and through the satellite to carry on the real-time comparison with the time service departments of various countries in the world. (excerpt from: https://zh.wikipedia.org/wiki/%E5%8C%97%E4%BA%AC%E6%97%B6%E9%97%B4)
DST daylight saving time (English: daylight time, UK and other regions), also known as daylight saving time (English: daylight saving time, DST, USA), is a way to speed up the time at the expense of the normal sunrise time in the summer month. Areas that usually use daylight saving time will speed up the time by an hour near the beginning of spring and return to normal time in autumn [1]. In fact, daylight saving time reduces sleep by an hour in spring and an hour more in autumn. (excerpt from: https://zh.wikipedia.org/wiki/%E5%A4%8F%E6%97%B6%E5%88%B6)
In April 1986, the relevant departments of the Chinese Central Committee issued a notice on the implementation of daylight saving time nationwide. The specific practice is to set the clock forward one hour from 2: 00 a.m. on the first Sunday in mid-April (Beijing time), that is, from 2 o'clock to 3 o'clock, daylight saving time begins. At 2: 00 a.m. on the first Sunday in mid-September (Beijing Daylight time), set the clock back to one hour, that is, the hands of the watch will be set from 2: 00 to 1, and daylight saving time will end. In the six years from 1986 to 1991, except that 1986 is the first year for the implementation of daylight saving time, from May 4 to September 14, all other years will be implemented in accordance with the prescribed time period. A few days before daylight saving time begins and ends, the news media publish notices from relevant departments. Daylight saving time has been suspended since 1992. (excerpt from: https://baike.baidu.com/item/%E5%A4%8F%E4%BB%A4%E6%97%B6)
March 1 to October 31, 1952. From 1953 to 1954, from April 1 to October 31 each year. From 1955 to 1956, from May 1 to September 30 each year. From 1957 to 1959, from April 1 to September 30 each year. From 1960 to 1961, from June 1 to September 30 each year. From 1974 to 1975, from April 1 to October 31 each year. July 1 to September 30, 1979. The details are as follows: 13 April to 14 September 1986, 12 April to 13 September 1987, 10 April to 11 September 1988, 16 April to 17 September 1989, 15 April to 16 September 1990, 14 April to 15 September 1991.
By comparison, we can see that the corresponding user's birthday "1988-07-29" in the application is within the daylight saving time zone in China, because our operating system, database and JDK all use the "Asia/Shanghai" time zone, so there should be no mistake. We also confirm that the result is fine through the debug result in the figure above.
Continue to troubleshoot the business layer and interface layer to locate the problem
The project uses spring boot to provide rest interface to return json messages, and uses spring default Jackson framework to parse. If you need to export a uniform date format in the project, configure Jackson as follows:
# jackson# date format spring.jackson.date-format=yyyy-MM-dd HH:mm:ssspring.jackson.time-zone=GMT+8
By looking at the JacksonProperties.java source code:
/ Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler) / / package org.springframework.boot.autoconfigure.jackson;import com.fasterxml.jackson.annotation.JsonInclude.Include;import com.fasterxml.jackson.core.JsonParser.Feature;import com.fasterxml.jackson.databind.DeserializationFeature;import com.fasterxml.jackson.databind.MapperFeature;import com.fasterxml.jackson.databind.SerializationFeature;import java.util.EnumMap;import java.util.Locale;import java.util.Map;import java.util.TimeZone Import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties (prefix = "spring.jackson") public class JacksonProperties {private String dateFormat; private String jodaDateTimeFormat; private String propertyNamingStrategy; private Map serialization = new EnumMap (SerializationFeature.class); private Map deserialization = new EnumMap (DeserializationFeature.class); private Map mapper = new EnumMap (MapperFeature.class); private Map parser = new EnumMap (Feature.class); private Map generator = new EnumMap (com.fasterxml.jackson.core.JsonGenerator.Feature.class); private Include defaultPropertyInclusion; private TimeZone timeZone = null Private Locale locale; public JacksonProperties () {} public String getDateFormat () {return this.dateFormat;} public void setDateFormat (String dateFormat) {this.dateFormat = dateFormat;} public String getJodaDateTimeFormat () {return this.jodaDateTimeFormat;} public void setJodaDateTimeFormat (String jodaDataTimeFormat) {this.jodaDateTimeFormat = jodaDataTimeFormat;} public String getPropertyNamingStrategy () {return this.propertyNamingStrategy;} public void setPropertyNamingStrategy (String propertyNamingStrategy) {this.propertyNamingStrategy = propertyNamingStrategy } public Map getSerialization () {return this.serialization;} public Map getDeserialization () {return this.deserialization;} public Map getMapper () {return this.mapper;} public Map getParser () {return this.parser;} public Map getGenerator () {return this.generator;} public Include getDefaultPropertyInclusion () {return this.defaultPropertyInclusion;} public void setDefaultPropertyInclusion (Include defaultPropertyInclusion) {this.defaultPropertyInclusion = defaultPropertyInclusion } public TimeZone getTimeZone () {return this.timeZone;} public void setTimeZone (TimeZone timeZone) {this.timeZone = timeZone;} public Locale getLocale () {return this.locale;} public void setLocale (Locale locale) {this.locale = locale;}}
Learn that the spring.jackson.time-zone attribute operates on java.util.TimeZone. So we simulated the conversion process through a piece of test code:
Package com.test;import java.sql.Date;import java.util.TimeZone;/** * @ author alexpdh * @ date 2019-07-17 * / public class Test {public static void main (String [] args) {System.out.println ("current default time zone is:" + TimeZone.getDefault () .getID ()); Date date1 = Date.valueOf ("1988-07-29") Date date2= Date.valueOf ("1983-07-29"); System.out.println ("time within China Daylight time" + date1); System.out.println ("normal East eighth District time date2= + date2"); / / Simulation spring.jackson.time-zone=GMT+8 attribute setting TimeZone zone= TimeZone.getTimeZone ("GMT+8") TimeZone.setDefault (zone); System.out.println (TimeZone.getDefault (). GetID ()); Date date3= date1; Date date4 = date2; System.out.println ("converted time date3= within China Daylight time" + date3) System.out.println ("converted normal East eighth District time date4=" + date4);}}
Output the result after running:
The current default time zone is: Asia/Shanghai time within China Daylight time range date1=1988-07-29 normal East Daylight time date2=1983-07-29GMT+08:00 converted time within China Daylight time range date3=1988-07-28 converted normal East Daylight time date4=1983-07-29
From here, we finally found the point of the problem. We can see from the debug picture that because that date is within the daylight saving time range of China, it takes an hour faster and uses the UTC/GMT+0900 format, while jackjson uses the UTC/GMT+0800 format when converting the message to json format. In other words, we need to slow down the JDK time zone by one hour to "1988-07-28 23:00:00" when we convert a time like UTC/GMT+0900 's "1988-07-29 00:00:00" to the standard East 8 UTC/GMT+0800 format.
Bug solution
It is easy to locate the problem and only need to modify the following settings:
# jackson# date format spring.jackson.date-format=yyyy-MM-dd HH:mm:ssspring.jackson.time-zone=Asia/Shanghai
The problem of keeping the time zone consistent has been solved.
At this point, I believe you have a deeper understanding of "how to troubleshoot the inconsistency between the output date format of the interface caused by JDK and the expected time". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.