1.时间工具类
public class DataUtil {
private static final Logger logger = LoggerFactory.getLogger(DataUtil.class);
private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT= new ThreadLocal<SimpleDateFormat>() {
@Override
protected synchronized SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyyMMdd");
}
};
private static final ThreadLocal<SimpleDateFormat> DATE_TIME_FORMAT= new ThreadLocal<SimpleDateFormat>() {
@Override
protected synchronized SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
//lang3 需要导入lang3包,如果是lang中的,则没有parse方法
private static FastDateFormat SOURCE_TIME_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss+08:00");
private static FastDateFormat GMT_TIME_FORMAT=FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
private static FastDateFormat UTC_TIME_FORMAT = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
/**
* 将yyyy-MM-dd HH:mm:ss 转化成 yyyyMMdd 格式
* @param datetime
* @return
*/
public static String date(String datetime){
String date="";
try {
Date parseDate = DATE_TIME_FORMAT.get().parse(datetime);
date = DATE_FORMAT.get().format(parseDate);
} catch (ParseException e) {
logger.error("将yyyy-MM-dd HH:mm:ss 转化成 yyyyMMdd 格式 解析错误 "+e.getMessage());
}
return date;
}
/**
* 将时间(yyyyMMdd格式字符串)转化为时间戳
* @param date
* @return
*/
public static Long getTimeStamp(String date){
long time=0L;
try {
Date parse = DATE_FORMAT.get().parse(date);
time = parse.getTime();
} catch (ParseException e) {
logger.error("将时间转化为时间戳错误"+e.getMessage());
}
return time;
}
/**
* 将时间转化为东八区时间
* @param date
* @return
*/
public static String getGMTTime(String date){
String GMTTime=null;
try {
Long timestamp=UTC_TIME_FORMAT.parse(date).getTime();
GMTTime = GMT_TIME_FORMAT.format(new Date(timestamp + 8 * 3600 * 1000));
} catch (ParseException e) {
e.printStackTrace();
}
return GMTTime;
}
/**
* 将时间转化为canal ES adapter的输出格式 yyyy-MM-dd'T'HH:mm:ss+08:00
* @param data
* @return
*/
public static String getFormatTime(String data){
String format=null;
try {
format = SOURCE_TIME_FORMAT.format(GMT_TIME_FORMAT.parse(data));
} catch (ParseException e) {
e.printStackTrace();
}
return format;
}
/**
* 验证指定时间格式
* @param str 时间
* @param timeFormat 时间格式
* @return
*/
public static boolean isValidDate(String str,String timeFormat) {
boolean convertSuccess = true;
// 指定日期格式为四位年-两位月份-两位日期 yyyy-MM-dd HH:mm:ss
SimpleDateFormat format = new SimpleDateFormat(timeFormat);
try {
// 设置lenient为false.
format.setLenient(false);
format.parse(str);
//时间格式必须一模一样(过滤掉时间中带T AM PM等样式时间)
if(timeFormat.length() != str.length()){
convertSuccess=false;
logger.error("时间格式长度不一致错误,源数据:[{}]",str);
}
} catch (Exception e) {
logger.error("时间格式解析错误,Exception:[{}] ,源数据:[{}]",e.getMessage(),str);
convertSuccess = false;
}
return convertSuccess;
}
public static void main(String[] args) {
System.out.println(getGMTTime("2020-12-20T01:34:56.526Z"));
}
}
备注:fastDateFormat需要导入commons-lang3包
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
2.canal adapter to es的时间类型
/**
* 2020-12-23T19:09:37.150+08:00 --> 其实还是 2020-12-23 19:09:37.150 为什么要这种时间??
* @param args
*/
public static void main(String[] args) {
//2020-12-23 19:09:37 1608721777150
String res;
DateTime dateTime = new DateTime(1608721777150L);
if (dateTime.getMillisOfSecond() != 0) {
res = dateTime.toString("yyyy-MM-dd'T'HH:mm:ss.SSS" + Util.timeZone);
} else {
res = dateTime.toString("yyyy-MM-dd'T'HH:mm:ss" + Util.timeZone);
}
System.out.println(res);
}
3.dataX中 写入es其中时间类型用到joda-time包
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.4</version>
</dependency>
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import java.util.TimeZone;
/**
* @author: XXX
* @date: 2020/12/24 16:54
* @Description: 测试
*/
public class TimeTest {
public final static String timeZone;
static {
TimeZone localTimeZone = TimeZone.getDefault();
int rawOffset = localTimeZone.getRawOffset();
String symbol = "+";
if (rawOffset < 0) {
symbol = "-";
}
rawOffset = Math.abs(rawOffset);
int offsetHour = rawOffset / 3600000;
int offsetMinute = rawOffset % 3600000 / 60000;
String hour = String.format("%1$02d", offsetHour);
String minute = String.format("%1$02d", offsetMinute);
timeZone = symbol + hour + ":" + minute;
}
/**
* 将13位时间戳转化为 东八区时间国际写法
* @param args
*/
public static void main(String[] args) {
String time="1597298196000";
//2020-08-13T13:56:36.000+08:00
DateTimeZone dtz = DateTimeZone.getDefault();
DateTime date = new DateTime(Long.valueOf(time), dtz);
System.out.println(date.toString()); //2020-08-13T13:56:36.000+08:00 ES东八区时间到毫秒国际写法
System.out.println(date.toString("yyyy-MM-dd'T'HH:mm:ss" + timeZone)); //2020-08-13T13:56:36+08:00 ES东八区时间到秒国际写法
}
}
dataX ES writer插件中,会把Mysql中默认为null的字段赋值一个当前时间,并同步到ES中,显然这样是不符合业务要求的,此处进行修改.
package com.alibaba.datax.plugin.writer.elasticsearchwriter;
public class ESWriter extends Writer 类中修改getDateStr方法
//为了dataX 离线同步ES时间与canal adapter实时同步到ES的时间格式一致性
public final static String timeZone;
static {
TimeZone localTimeZone = TimeZone.getDefault();
int rawOffset = localTimeZone.getRawOffset();
String symbol = "+";
if (rawOffset < 0) {
symbol = "-";
}
rawOffset = Math.abs(rawOffset);
int offsetHour = rawOffset / 3600000;
int offsetMinute = rawOffset % 3600000 / 60000;
String hour = String.format("%1$02d", offsetHour);
String minute = String.format("%1$02d", offsetMinute);
timeZone = symbol + hour + ":" + minute;
}
/**
* ES 时间字段解析
* @param esColumn
* @param column
* @return
*/
private String getDateStr(ESColumn esColumn, Column column) {
DateTime date = null;
DateTimeZone dtz = DateTimeZone.getDefault();
if (esColumn.getTimezone() != null) {
dtz = DateTimeZone.forID(esColumn.getTimezone());
}
if (column.getType() != Column.Type.DATE && esColumn.getFormat() != null) {
//根据json配置中的format来解析 { "name": "createTime","type": "date", "format": "yyyy-MM-dd HH:mm:ss" }
DateTimeFormatter formatter = DateTimeFormat.forPattern(esColumn.getFormat());
date = formatter.withZone(dtz).parseDateTime(column.asString());
return date.toString();
} else if (column.getType() == Column.Type.DATE) {
//es中的字段类型为date,走的是此方法
if(column.asLong() != null){
date = new DateTime(column.asLong(), dtz);
//为了dataX 离线同步ES时间与canal adapter实时同步到ES的时间格式一致性,将date格式化为东八区国际时间到秒
return date.toString("yyyy-MM-dd'T'HH:mm:ss" + timeZone);
}
return null;
} else {
return column.asString();
}
}