- 论坛徽章:
- 9
|
本帖最后由 wlmqgzm 于 2016-05-30 08:51 编辑
// 本段代码主要是压缩日期和时间为整数, 结合前面给出的整数压缩编码的方案, 可以用更少的字节数, 最终实现更高效率的存储
// 综合考虑, 如果直接使用日期和时间等各C++对象, 效率不高,, 最终还是要自己做代码来提高性能,
// 因此, 干脆直接全部使用自己的代码来实现, 总体上以效率为准
// 方案一: 年9999, 可以用2个字节,最大到65535, 月12用1个字节, 日31用一个字节, 这样总共4个字节, 中间不做转换,效率最高
// 通用代码来实现, 这样1个整数, 4个字节, 头2个字节就是年, 后1个字节就是月, 最后一个字节就是日, 简单的substr操作就可以.
// 方案二: 20160424整体作为整数, 除以10000就是年, 余数0424, 再除以100就是月4, 余数就是日24, 这个方案最大可表示20万年
// 方案三: 2016, 04, 24 整数=2016*12*31+4*31 + 24, 除以12*31=年份,余数部分除以31就是4月,余数就是24日,这个方案表示的年份最大
// 方案四: 直接用离1970/01/01的Unix日子来表示, 这个主要的优点是计算方便,可以不用转换,直接计算, 缺点是输出的时候(这个是最常用的功能), 计算比较繁琐,性能低
// 综合考虑下来, 就采用方案3来存放, 一般的大小比较可以直接比较, 其他的日期计算的就需要转化,
// 这里不得不用如此多的代码来实现的一个原因是: 对现有的代码表示的日期范围不满意
// 将一个字符串表示的日期, "20160120", "2016/1/29", "2016-1-24"这样类似的三种格式统一转化为一个32位的整数
// 最大可以表示11545611年, 即1154万年以后的情况
// 出错返回0, 其他返回一个大于零的整数
// 允许的日期从0000/01/01开始, 到11545611/12/31为止
- // 判断是否是闰年
- bool year_is_leap( unsigned int int_year )
- {
- if( int_year%400==0 ) return true;
- if( int_year%100==0 ) return false;
- if( int_year%4==0 ) return true;
- return false;
- }
- unsigned int string_to_uint_date( const std::string &str_in, std::string &str_error )
- {
- unsigned int uint_year;
- unsigned int uint_month;
- unsigned int uint_day;
- std::string str_tmp;
- std::string str_cmp;
- std::vector<std::string> vt_str_out;
- std::string str_year;
- std::string str_month;
- std::string str_day;
- std::vector<unsigned int>vt_int_day = {31,29,31,30,31,30, 31,31,30,31,30,31 };
- std::vector<std::string>vt_str_month1 = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
- std::vector<std::string>vt_str_month2 = { "JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC" };
- bool bool_has_abc ;
- str_error.clear();
- unsigned int n = str_in.length();
- if( n < 6 ) {
- str_error = str_in;
- str_error += " is too short.";
- return 0;
- }
- // 获得特殊字符, 存放到str_cmp; 可以支持- / _等情况
- for( unsigned int i=0; i<n; ++i ) {
- str_tmp = str_in.substr( i, 1 );
- if( str_tmp>="0" && str_tmp<="9" ) continue;
- str_cmp = str_tmp;
- break;
- }
- // 检查是否存在字母
- bool_has_abc = string_has_abc( str_in );
- if( str_cmp.empty() ) { // 表示没有特殊字符隔离, 说明全部是数字
- if( bool_has_abc ) { // 如果没有特殊字符隔离又有字母, 出错
- str_error = str_in;
- str_error += " has abc and no find - or /.";
- return 0;
- }
- // 表示没有特殊字符隔离, 没有字母, 说明全部是数字
- str_year = str_in.substr( 0, str_in.length()-4 ); // 保留除最后4位的就是年
- str_month = str_in.substr( str_in.length()-4, 2 ); // 保留最后4位开始的2字节就是月
- str_day = str_in.substr( str_in.length()-2, 2 ); // 最后2位是日
- }
- else {
- string_to_vector_string( str_in, str_cmp, vt_str_out );
- if( vt_str_out.size()>3) {
- str_error = str_in;
- str_error += " has too many data.";
- return 0;
- }
- if( 3==vt_str_out.size() ) {
- str_year = vt_str_out[0];
- str_month = vt_str_out[1];
- str_day = vt_str_out[2];
- if( bool_has_abc ) { // 如果有字母, 则转换字母月份到数字月份
- for( unsigned int i=0, n=12; i<n; ++i ) {
- if( vt_str_month1[i] != str_month && vt_str_month2[i] != str_month ) continue;
- str_month = std::to_string( i+1 );
- continue;
- }
- }
- }
- }
- if( str_year.empty() || str_year.length()>8 || !string_is_number( str_year ) ) {
- str_error = "str_in=";
- str_error += str_in;
- str_error += ", str_year=";
- str_error += str_year;
- str_error += ", year is bad.";
- return 0;
- }
- if( str_month.empty() || str_month.length()>2 || !string_is_number( str_month ) ) {
- str_error = "str_in=";
- str_error += str_in;
- str_error += ", str_month=";
- str_error += str_month;
- str_error += ", month is bad.";
- return 0;
- }
- if( str_day.empty() || str_month.length()>2 || !string_is_number( str_day ) ) {
- str_error = "str_in=";
- str_error += str_in;
- str_error += ", str_day=";
- str_error += str_day;
- str_error += ", day is bad.";
- return 0;
- }
- uint_year = boost::lexical_cast<unsigned int>( str_year );
- if( uint_year>256L*256*256*256/12/31 ) {
- str_error = str_in;
- str_error += ", year is error.";
- return 0;
- }
- uint_month = boost::lexical_cast<unsigned int>( str_month );
- if( uint_month<1 || uint_month>12 ) {
- str_error = str_in;
- str_error += ", month is error.";
- return 0;
- }
- uint_day = boost::lexical_cast<unsigned int>( str_day );
- if( uint_day<1 || uint_day>31 ) {
- str_error = str_in;
- str_error += ", day is error.";
- return 0;
- }
- if( 2==uint_month ) { // 处理特殊的2月
- if( !year_is_leap( uint_year ) && uint_day==29 ) { // 非闰年有29日的报错
- str_error = str_in;
- str_error += ", day is error. not a leapyear. day can not be 29 in this month.";
- return 0;
- }
- }
- if( uint_day > vt_int_day[uint_month-1] ) {
- str_error = str_in;
- str_error += ", day is error. max day in this month is ";
- str_error += std::to_string( vt_int_day[uint_month-1] );
- return 0;
- }
- return uint_year*12*31 + uint_month*31 + uint_day;
- }
- unsigned int ymd_to_uint_date( const unsigned int uint_year, const unsigned int uint_month, const unsigned int uint_day, std::string &str_error )
- {
- std::vector<unsigned int>vt_int_day = {31,29,31,30,31,30, 31,31,30,31,30,31 };
- if( uint_year>256L*256*256*256/12/31 ) {
- str_error = "year is error. year=";
- str_error += std::to_string( uint_year );
- return 0;
- }
- if( uint_month<1 || uint_month>12 ) {
- str_error = "month is error. month=";
- str_error += std::to_string( uint_month );
- return 0;
- }
- if( uint_day<1 || uint_day>31 ) {
- str_error = "day is error. day=";
- str_error += std::to_string( uint_day );
- return 0;
- }
- if( 2==uint_month ) { // 处理特殊的2月
- if( !year_is_leap( uint_year ) && uint_day==29 ) { // 非闰年有29日的报错
- str_error = "day is error. not a leapyear. year=";
- str_error += std::to_string( uint_year );
- str_error += ", month=";
- str_error += std::to_string( uint_month );
- str_error += ", day=";
- str_error += std::to_string( uint_day );
- return 0;
- }
- }
- if( uint_day > vt_int_day[uint_month-1] ) {
- str_error = "day is error. max day in this month is ";
- str_error += std::to_string( vt_int_day[uint_month-1] );
- str_error += ", month=";
- str_error += std::to_string( uint_month );
- str_error += ", day=";
- str_error += std::to_string( uint_day );
- return 0;
- }
- return uint_year*12*31 + uint_month*31 + uint_day;
- }
- void uint_date_to_string( const unsigned int uint_date, std::string &str_date )
- {
- unsigned int uint_year;
- unsigned int uint_month;
- unsigned int uint_day;
- unsigned int uint_excess; // 余数
- std::string str_year;
- std::string str_month;
- std::string str_day;
- std::string str_tmp;
- uint_year = uint_date / 372; // 12*31=372
- uint_excess = uint_date % 372;
- uint_month = uint_excess / 31;
- uint_day = uint_excess % 31;
- str_year = std::to_string( uint_year );
- str_month = std::to_string( uint_month );
- str_day = std::to_string( uint_day );
- /* std::cout << "str_year=" << str_year << std::endl;
- std::cout << "str_month=" << str_month << std::endl;
- std::cout << "str_day=" << str_day << std::endl; */
- while( str_year.length()<4 ) {
- str_tmp = "0";
- str_tmp += str_year;
- str_year = str_tmp;
- }
- if( str_month.length()<2 ) {
- str_tmp = "0";
- str_tmp += str_month;
- str_month = str_tmp;
- }
- if( str_day.length()<2 ) {
- str_tmp = "0";
- str_tmp += str_day;
- str_day = str_tmp;
- }
- str_date = str_year ;
- str_date += "-";
- str_date += str_month;
- str_date += "-";
- str_date += str_day;
- std::cout << str_date << std::endl << std::endl;
- return;
- }
- void uint_date_to_ymd( const unsigned int uint_date, unsigned int &uint_year, unsigned int &uint_month, unsigned int &uint_day )
- {
- unsigned int uint_excess; // 余数
- std::string str_year;
- std::string str_month;
- std::string str_day;
- std::string str_tmp;
- uint_year = uint_date / 372; // 12*31=372
- uint_excess = uint_date % 372;
- uint_month = uint_excess / 31;
- uint_day = uint_excess % 31;
- return;
- }
- // 将一个字符串转化为一个整数, 表示从00:00:00过的秒数
- unsigned int string_to_uint_time( const std::string &str_in, std::string &str_error )
- {
- unsigned int uint_hour;
- unsigned int uint_minute;
- unsigned int uint_second;
- std::string str_tmp;
- std::string str_cmp;
- std::string str_hour;
- std::string str_minute;
- std::string str_second;
- std::vector<std::string> vt_str_out;
- str_error.clear();
- unsigned int n = str_in.length();
- if( n < 6 ) {
- str_error = str_in;
- str_error += " is too short.";
- return 0;
- }
- // 获得特殊字符, 存放到str_cmp; 可以支持- / _等情况
- for( unsigned int i=0; i<n; ++i ) {
- str_tmp = str_in.substr( i, 1 );
- if( str_tmp>="0" && str_tmp<="9" ) continue;
- str_cmp = str_tmp; // 获取第1个非数字的字符
- break;
- }
- if( string_has_abc( str_in ) ) { // 如果有字母, 出错
- str_error = str_in;
- str_error += " , time must not have abc.";
- return 0;
- }
- if( str_cmp.empty() ) { //
- str_hour = str_in.substr( 0, 2 ); //
- str_minute = str_in.substr( 2, 2 ); //
- str_second = str_in.substr( 4, 2 ); //
- }
- else {
- string_to_vector_string( str_in, str_cmp, vt_str_out );
- if( vt_str_out.size()>3) {
- str_error = str_in;
- str_error += " has too many data.";
- return 0;
- }
- if( 3==vt_str_out.size() ) {
- str_hour = vt_str_out[0];
- str_minute = vt_str_out[1];
- str_second = vt_str_out[2];
- }
- }
- if( str_hour.length() != 2 || !string_is_number( str_hour ) ) {
- str_error = "str_in=";
- str_error += str_in;
- str_error += ", str_hour=";
- str_error += str_hour;
- str_error += ", hour is bad.";
- return 0;
- }
- if( str_minute.length() != 2 || !string_is_number( str_minute ) ) {
- str_error = "str_in=";
- str_error += str_in;
- str_error += ", str_minute=";
- str_error += str_minute;
- str_error += ", minute is bad.";
- return 0;
- }
- if( str_second.length() != 2 || !string_is_number( str_second ) ) {
- str_error = "str_in=";
- str_error += str_in;
- str_error += ", str_second=";
- str_error += str_second;
- str_error += ", second is bad.";
- return 0;
- }
- std::cout << "hour=" << str_hour << std::endl;
- std::cout << "minute=" << str_minute << std::endl;
- std::cout << "second=" << str_second << std::endl;
- uint_hour = boost::lexical_cast<unsigned int>( str_hour );
- if( uint_hour>23 ) {
- str_error = str_in;
- str_error += ", hours must below 24.";
- return 0;
- }
- uint_minute = boost::lexical_cast<unsigned int>( str_minute );
- if( uint_minute>60 ) {
- str_error = str_in;
- str_error += ", minutes must below 60.";
- return 0;
- }
- uint_second = boost::lexical_cast<unsigned int>( str_second );
- if( uint_second>60 ) {
- str_error = str_in;
- str_error += ", seconds must below 60.";
- return 0;
- }
- return uint_hour*3600 + uint_minute*60 + uint_second;
- }
- unsigned long string_to_ulong_datetime( const std::string &str_in, std::string &str_error )
- {
- unsigned long ulong_date;
- unsigned long ulong_time;
- std::string str_date;
- std::string str_time;
- std::vector<std::string> vt_str_out;
- std::string str_cmp = " ";
- string_to_vector_string( str_in, str_cmp, vt_str_out );
- if( vt_str_out.size()>2) {
- str_error = str_in;
- str_error += " has too many blank.";
- return 0;
- }
- if( 2==vt_str_out.size() ) {
- str_date = vt_str_out[0];
- str_time = vt_str_out[1];
- }
- ulong_date = string_to_uint_date( str_date, str_error );
- if( !str_error.empty() ) return 0;
- ulong_time = string_to_uint_time( str_time, str_error );
- if( !str_error.empty() ) return 0;
- //ulong_ret = ulong_date * 86400L + ulong_time;
- return ulong_date * 86400L + ulong_time;
- }
- void uint_time_to_string( const unsigned int uint_time, std::string &str_time )
- {
- unsigned int uint_hour;
- unsigned int uint_minute;
- unsigned int uint_second;
- unsigned int uint_excess; // 余数
- std::string str_hour;
- std::string str_minute;
- std::string str_second;
- std::string str_tmp;
- uint_hour = uint_time / 3600; // 12*31=372
- uint_excess = uint_time % 3600;
- uint_minute = uint_excess / 60;
- uint_second = uint_excess % 60;
- str_hour = std::to_string( uint_hour );
- str_minute = std::to_string( uint_minute );
- str_second = std::to_string( uint_second );
- /* std::cout << "str_hour=" << str_hour << std::endl;
- std::cout << "str_minute=" << str_minute << std::endl;
- std::cout << "str_second=" << str_second << std::endl; */
- if( str_hour.length()<2 ) {
- str_tmp = "0";
- str_tmp += str_hour;
- str_hour = str_tmp;
- }
- if( str_minute.length()<2 ) {
- str_tmp = "0";
- str_tmp += str_minute;
- str_minute = str_tmp;
- }
- if( str_second.length()<2 ) {
- str_tmp = "0";
- str_tmp += str_second;
- str_second = str_tmp;
- }
- str_time = str_hour;
- str_time += ":";
- str_time += str_minute;
- str_time += ":";
- str_time += str_second;
- std::cout << str_time << std::endl << std::endl;
- return;
- }
- void ulong_datetime_to_string( const unsigned long ulong_datetime, std::string &str_datetime )
- {
- //unsigned long ulong_date;
- //unsigned long ulong_time;
- unsigned int uint_date;
- unsigned int uint_time;
- std::string str_date;
- std::string str_time;
- uint_date = ulong_datetime / 86400L;
- uint_time = ulong_datetime % 86400L;
- uint_date_to_string( uint_date, str_date );
- uint_time_to_string( uint_time, str_time );
- str_datetime = str_date;
- str_datetime += " ";
- str_datetime += str_time;
- return;
- }
- void uint_time_to_hms( const unsigned int uint_time, unsigned int &uint_hour, unsigned int &uint_minute, unsigned int &uint_second )
- {
- unsigned int uint_excess; // 余数
- std::string str_hour;
- std::string str_minute;
- std::string str_second;
- std::string str_tmp;
- uint_hour = uint_time / 3600; // 12*31=372
- uint_excess = uint_time % 3600;
- uint_minute = uint_excess / 60;
- uint_second = uint_excess % 60;
- return;
- }
- void ulong_datetime_to_ymdhms( const unsigned long ulong_datetime,
- unsigned int &uint_year, unsigned int &uint_month, unsigned int &uint_day,
- unsigned int &uint_hour, unsigned int &uint_minute, unsigned int &uint_second )
- {
- unsigned int uint_date;
- unsigned int uint_time;
- uint_date = ulong_datetime / 86400L;
- uint_time = ulong_datetime % 86400L;
- uint_date_to_ymd( uint_date, uint_year, uint_month, uint_day );
- uint_time_to_hms( uint_time, uint_hour, uint_minute, uint_second );
- return;
- }
复制代码 |
|