impala保存时间类型timestamp---NanoTimeUtils根据JdateTime生成nanotime

在Impala中,时间字段以int96格式存储,需将常规时间如2017-05-23 11:59:43.345717转换为timestamp。此过程涉及Julian day,通过JdateTime生成nanotime,再转为Binary存储在HDFS。NanoTimeUtils用于根据JdateTime生成nanotime,注意转换时要考虑时区差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

impala中时间字段采用int96保存,常规时间如:2017-05-23 11:59:43.345717要保存为timestamp类型,则需要经过转换才能使用。采用Julian day来格式化时间,利用JdateTime生成nanotime然后转换为Binary保存到hdfs.NanoTimeUtils根据JdateTime生成nanotime

注意时区:不同时区生成的结果不同

/**
 * 创建日期:2017-8-4
 * 包路径:org.meter.parquet.NanoTimeUtils.java
 * 创建者:meter
 * 描述:
 * 版权:copyright@2017 by meter !
 */
package org.meter.parquet;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.TimeZone;

import org.apache.parquet.example.data.simple.NanoTime;


import jodd.datetime.JDateTime;
/**
 * @author meter 
 * 文件名:NanoTimeUtils
 * @描述:NanoTime工具,用于保存parquet文件timestamp类型字段
 */
public class NanoTimeUtils {

	static final long NANOS_PER_SECOND = 1000000000;
	static final long SECONDS_PER_MINUTE = 60;
	static final long MINUTES_PER_HOUR = 60;

	private static final ThreadLocal<Calendar> parquetTsCalendar = new ThreadLocal<Calendar>();

	private static Calendar getCalendar() {
		// Calendar.getInstance calculates the current-time needlessly, so cache
		// an instance.
		if (parquetTsCalendar.get() == null) {
			parquetTsCalendar.set(Calendar.getInstance(TimeZone
					.getTimeZone("Asia/Shanghai")));
		}
		return parquetTsCalendar.get();
	}

	public static NanoTime getNanoTime(Timestamp ts) {

		Calendar calendar = getCalendar();
		calendar.setTime(ts);
		JDateTime jDateTime = new JDateTime(calendar.get(Calendar.YEAR),
				calendar.get(Calendar.MONTH) + 1, // java calendar index
													// starting at 1.
				calendar.get(Calendar.DAY_OF_MONTH));
		int days = jDateTime.getJulianDayNumber();

		long hour = calendar.get(Calendar.HOUR_OF_DAY);
		long minute = calendar.get(Calendar.MINUTE);
		long second = calendar.get(Calendar.SECOND);
		long nanos = ts.getNanos();
		long nanosOfDay = nanos + NANOS_PER_SECOND * second + NANOS_PER_SECOND
				* SECONDS_PER_MINUTE * minute + NANOS_PER_SECOND
				* SECONDS_PER_MINUTE * MINUTES_PER_HOUR * hour;
		return new NanoTime(days, nanosOfDay);
	}

	public static NanoTime getNanoTime(String time){
		Timestamp ts=Timestamp.valueOf(time);
		Calendar calendar = getCalendar();
		calendar.setTime(ts);
		JDateTime jDateTime = new JDateTime(calendar.get(Calendar.YEAR),
				calendar.get(Calendar.MONTH) + 1, // java calendar index
													// starting at 1.
				calendar.get(Calendar.DAY_OF_MONTH));
		int days = jDateTime.getJulianDayNumber();

		long hour = calendar.get(Calendar.HOUR_OF_DAY);
		long minute = calendar.get(Calendar.MINUTE);
		long second = calendar.get(Calendar.SECOND);
		long nanos = ts.getNanos();
		long nanosOfDay = nanos + NANOS_PER_SECOND * second + NANOS_PER_SECOND
				* SECONDS_PER_MINUTE * minute + NANOS_PER_SECOND
				* SECONDS_PER_MINUTE * MINUTES_PER_HOUR * hour;
		return new NanoTime(days, nanosOfDay);
	
	}
	public static Timestamp getTimestamp(NanoTime nt) {
		int julianDay = nt.getJulianDay();
		long nanosOfDay = nt.getTimeOfDayNanos();

		JDateTime jDateTime = new JDateTime((double) julianDay);
		Calendar calendar = getCalendar();
		calendar.set(Calendar.YEAR, jDateTime.getYear());
		calendar.set(Calendar.MONTH, jDateTime.getMonth() - 1); // java calender
																// index
																// starting at
																// 1.
		calendar.set(Calendar.DAY_OF_MONTH, jDateTime.getDay());

		long remainder = nanosOfDay;
		int hour = (int) (remainder / (NANOS_PER_SECOND * SECONDS_PER_MINUTE * MINUTES_PER_HOUR));
		remainder = remainder
				% (NANOS_PER_SECOND * SECONDS_PER_MINUTE * MINUTES_PER_HOUR);
		int minutes = (int) (remainder / (NANOS_PER_SECOND * SECONDS_PER_MINUTE));
		remainder = remainder % (NANOS_PER_SECOND * SECONDS_PER_MINUTE);
		int seconds = (int) (remainder / (NANOS_PER_SECOND));
		long nanos = remainder % NANOS_PER_SECOND;

		calendar.set(Calendar.HOUR_OF_DAY, hour);
		calendar.set(Calendar.MINUTE, minutes);
		calendar.set(Calendar.SECOND, seconds);
		Timestamp ts = new Timestamp(calendar.getTimeInMillis());
		ts.setNanos((int) nanos);
		return ts;
	}

	public static void main(String[] args) {
		getNanoTime("2017-05-23 11:59:43.345717");
	}
}
测试类:写parquet格式文件,用于impala操作timestamp字段access_time;impala中timestamp字段类型保存为int96
/**
 * 创建日期:2017-8-3
 * 包路径:org.meter.parquet.ParquetWriteTimeStampDemo.java
 * 创建者:meter
 * 描述:
 * 版权:copyright@2017 by meter !
 */
package org.meter.parquet;

import java.io.IOException;
import jodd.datetime.JDateTime;
import org.apache.hadoop.fs.Path;
import org.apache.parquet.column.ParquetProperties;
import org.apache.parquet.example.data.Group;
import org.apache.parquet.example.data.simple.SimpleGroupFactory;
import org.apache.parquet.hadoop.ParquetFileWriter;
import org.apache.parquet.hadoop.ParquetWriter;
import org.apache.parquet.hadoop.example.ExampleParquetWriter;
import org.apache.parquet.hadoop.metadata.CompressionCodecName;
import org.apache.parquet.schema.MessageType;
import org.apache.parquet.schema.MessageTypeParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author meter
 * 文件名:ParquetWriteTimeStampDemo
 * @描述:
 */
public class ParquetWriteTimeStampDemo {

	private static Logger logger = LoggerFactory
			.getLogger(ParquetWriteTimeStampDemo.class);
	private static String schemaStr = "message schema {"
			+ "optional int64 log_id;" + "optional binary idc_id;"
			+ "optional int64 house_id;" + "optional int64 src_ip_long;"
			+ "optional int64 dest_ip_long;" + "optional int64 src_port;"
			+ "optional int64 dest_port;" + "optional int32 protocol_type;"
			+ "optional binary url64;" + "optional int96 access_time;}";
	private static MessageType schema = MessageTypeParser
			.parseMessageType(schemaStr);
	private static SimpleGroupFactory groupFactory = new SimpleGroupFactory(
			schema);

	/**
	 * 创建时间:2017-8-3
	 * 创建者:meter
	 * 返回值类型:ParquetWriter
	 * @描述:初始化writer
	 * @param path
	 * @return
	 * @throws IOException
	 */
	private static ParquetWriter<Group> initWriter(String path) throws IOException {
		Path file = new Path("file:///"+path);
		ExampleParquetWriter.Builder builder = ExampleParquetWriter
				.builder(file).withWriteMode(ParquetFileWriter.Mode.CREATE)
				.withWriterVersion(ParquetProperties.WriterVersion.PARQUET_1_0)
				.withCompressionCodec(CompressionCodecName.SNAPPY)
				// .withConf(configuration)
				.withType(schema);
		/*
		 * file, new GroupWriteSupport(), CompressionCodecName.SNAPPY, 256 *
		 * 1024 * 1024, 1 * 1024 * 1024, 512, true, false,
		 * ParquetProperties.WriterVersion.PARQUET_1_0, conf
		 */
		return builder.build();
	}

	
	/**
	 * 创建时间:2017-8-3 创建者:meter 返回值类型:void
	 * 
	 * @描述:
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		ParquetWriter<Group> writer = initWriter("C:\\Users\\meir\\Desktop\\linuxtetdir\\logtxt\\testTime0804.parq");
		String[] access_log = { "111111", "22222", "33333", "44444", "55555",
				"666666", "777777", "888888", "999999", "2017-05-23 11:59:43.345717" };
		JDateTime time=new JDateTime("2017-05-23 11:59:43.345717");
		int day=time.getDay();
		
		for(int i=0;i<1000;i++){
		writer.write(groupFactory.newGroup()
				.append("log_id", Long.parseLong(access_log[0]))
				.append("idc_id", access_log[1])
				.append("house_id", Long.parseLong(access_log[2]))
				.append("src_ip_long", Long.parseLong(access_log[3]))
				.append("dest_ip_long", Long.parseLong(access_log[4]))
				.append("src_port", Long.parseLong(access_log[5]))
				.append("dest_port", Long.parseLong(access_log[6]))
				.append("protocol_type", Integer.parseInt(access_log[7]))
				.append("url64", access_log[8])
				.append("access_time", NanoTimeUtils.getNanoTime(access_log[9]).toBinary()));
		}
		writer.close();
	}

}



<think>好的,我现在需要解决用户的问题:如何在Impala中将日期格式化为yyyy-MM-dd格式。首先,我得回忆一下Impala支持的日期函数和相关转换方法。 根据用户提供的引用[2],用户提到在Impala中使用SQL来转换YYYYMMDD格式的字符串为日期格式。这可能涉及到字符串到日期的转换,以及格式化输出。另外,引用[3]中提到了unix_timestamp函数的使用,可以将不同格式的字符串转换为时间戳,这可能对处理日期有帮助。 首先,如果原始数据是字符串类型,比如像'20231015'这样的YYYYMMDD格式,需要将其转换为日期类型。Impala的FROM_UNIXTIME和UNIX_TIMESTAMP函数可能有用。例如,使用UNIX_TIMESTAMP将字符串解析为时间戳,再通过FROM_UNIXTIME格式化为所需的格式。不过要注意,UNIX_TIMESTAMP需要指定输入格式,比如'yyyyMMdd'。 然后,如果数据已经是日期或时间戳类型,可以直接使用DATE_FORMAT函数来格式化为yyyy-MM-dd。DATE_FORMAT的第二个参数指定输出格式,这里应该是'%Y-%m-%d'。 另外,需要考虑数据类型。如果字段是STRING类型存储的日期,可能需要先转换为TIMESTAMP,再进行格式化。例如,使用CAST函数将字符串转换为TIMESTAMP,但需要确保字符串的格式能被Impala正确识别,否则可能出错。 还需要验证示例是否正确。例如,对于字符串'20231015',使用UNIX_TIMESTAMP('20231015', 'yyyyMMdd')得到时间戳,然后用FROM_UNIXTIME转换为'yyyy-MM-dd'格式,结果应该是'2023-10-15'。同时,如果日期字段已经是TIMESTAMP类型,直接用DATE_FORMAT(column, '%Y-%m-%d')即可。 此外,用户可能需要处理不同的原始格式,比如是否有时间部分,或者是否需要处理其他分隔符。根据情况调整格式字符串。 总结步骤应该是:确定原始数据类型和格式,选择合适的转换函数(如UNIX_TIMESTAMP和FROM_UNIXTIME组合,或DATE_FORMAT),然后应用格式化。同时,注意处理可能的异常情况,比如无效的日期字符串。</think>在Impala中将日期格式化为$yyyy\text{-}MM\text{-}dd$格式,可以通过以下方法实现: ### 方法1:字符串类型转换 若原始数据是$STRING$类型且格式为$yyyyMMdd$,使用组合函数: ```sql SELECT FROM_UNIXTIME(UNIX_TIMESTAMP('20231015', 'yyyyMMdd'), 'yyyy-MM-dd'); -- 输出结果:2023-10-15 ``` 该方法通过`UNIX_TIMESTAMP`解析原始字符串为时间戳,再通过`FROM_UNIXTIME`格式化为目标样式[^2][^3]。 ### 方法2:日期/时间戳类型转换 若字段是$TIMESTAMP$或$DATE$类型,直接使用格式化函数: ```sql SELECT DATE_FORMAT(NOW(), '%Y-%m-%d'); -- 输出当前日期如2023-10-15 ``` ### 方法3:带分隔符的字符串转换 若原始字符串含分隔符但格式不标准(如$yyyy/M/d$),需显式定义输入格式: ```sql SELECT FROM_UNIXTIME(UNIX_TIMESTAMP('2023/9/5', 'yyyy/M/d'), 'yyyy-MM-dd'); -- 输出结果:2023-09-05 ``` ### 参数说明 | 函数 | 作用 | 格式符号对照 | |-------------------|-------------------------------------|---------------------| | `UNIX_TIMESTAMP` | 将字符串转为时间戳(需指定输入格式) | $yyyy$=年,$MM$=月 | | `FROM_UNIXTIME` | 将时间戳转为格式化字符串 | $dd$=日,$HH$=小时 | | `DATE_FORMAT` | 直接格式化日期/时间戳类型 | $mm$=分钟,$ss$=秒 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值