2) 日期操作函数:
这些函数都和日期操作相关,具体请参考代码,注释应该比较清楚的。
/*
blf: 函数参数都是以指针方式传入(java或c#中就为传引用,swig将指针会转换为类对象,所有类对象在java和c#中都是传引用的.
c#支持struct,是值类型
c#还支持参数的ref和out方式,可以将值类型以传引用方式输出到参数中,相当于c中的指针
经验之谈:除非在c/c++中你使用shared_ptr等智能指针,否则千万不要在函数或成员方法中malloc或new一个新对象然后return出来。
比较好的方式还是通过参数传指针或引用方式来返回更新的数据。
*/
void date_set(SDate* ret,int year,int month,int day)
{
assert(ret);
ret->year = year;
ret->month = month;
ret->day = day;
}
/*
blf: 获取当前的年月日
*/
void date_get_now(SDate* ret)
{
assert(ret);
//time()此函数会返回从公元 1970 年1 月1 日的UTC 时间从0 时0 分0 秒算起到现在所经过的秒数。
//记住:是秒数,而不是毫秒数(很多语言返回的是毫秒数,crt中是以秒为单位的)
//如果t 并非空指针的话,此函数也会将返回值存到t指针所指的内存
time_t t;
time(&t);
//转换到当前系统的本地时间
struct tm* timeInfo;
timeInfo = localtime(&t);
//tm结构中的年份是从1900开始到今天的年数,因此需要加上1900
ret->year = timeInfo->tm_year + 1900;
//月份是 0 base的,我们按照1-12的方式来计算,因此加1
ret->month = timeInfo->tm_mon + 1;
ret->day = timeInfo->tm_mday;
}
/*
blf: 是否相等
*/
bool date_is_equal(const SDate* left,const SDate* right)
{
assert(left&&right);
return (left->year == right->year &&
left->month == right->month &&
left->day == right->day);
}
/*
blf: 计算两个年份之间的月数
*/
int date_get_month_count_from_year_range(int startYear,int endYear)
{
int diff = endYear - startYear + 1;
return diff * 12;
}
/*
blf: 将一维的数据表示映射成二维表示(年和月)
startYear表示起始年,例如 2010年
idx表示相对2010年开始的月份偏移量
我们会在下面和后面代码中看到/ 和 %的多次使用
可以理解为,将一维数据映射成二维行列表示的数据时,都可以使用这种方式
下面这个函数用于月历区间选择控件,例如你有个数据库查询需求,可以查询
当前年月日----五年前的年1月1号之间的数据,此时在UITabelView或ListView时,就需要
调用本函数来显示年月信息等
*/
void date_map_index_to_year_month(SDate* to,int startYear,int idx)
{
assert(to);
//每年有12个月,idx/12你可以看成每12个月进一位,加上startYear基准值,就可以获得当前年份
to->year = startYear + idx / 12;
//每年有12个月,idx%12你可以看成【0-11】之间循环,加1是因为我们的SDate结构是1-12表示的
to->month = idx % 12 + 1;
//至于day,这里为-1,我们在map中忽略该值,可以设置任意值
to->day = -1;
}
/*
blf: 下面函数来源于linux实现,计算从某个时间点(年月日时分秒)到1970年0时0分0秒的时间差
参考url: http://blog.csdn.net/axx1611/article/details/1792827
*/
long mymktime (unsigned int year, unsigned int mon,
unsigned int day, unsigned int hour,
unsigned int min, unsigned int sec)
{
if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
mon += 12; /* Puts Feb last since it has leap day */
year -= 1;
}
return (((
(long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
year*365 - 719499
)*24 + hour /* now have hours */
)*60 + min /* now have minutes */
)*60 + sec; /* finally seconds */
}
/*
blf: 下面函数一共实现了三个版本
第一版: 不知道是我对c的mktime用法错误还是有bug(理论上不可能,因为ios和android中都存在问题)
同一个时间点,例如2016年1月1日0时0分1秒与1970年1月1日0时0分0秒的时间差不一样。
第二版: 使用ios自身的 NSCalendar对象计算时间差,这个计算是正确的,但是只能用在ios中
第三版: http://blog.csdn.net/axx1611/article/details/1792827中的算法,来自于linux源码,ios/android中运行的很好
为什么不用time_t而是使用long呢?
这是因为android中使用swig将c/c++ 代码转换成java jni封装的函数时,time_t被封装成了对象。
因为java不认识c的typedef结构,Swig将其转换为SWITGYPT_p_XXXXX类型的包装(经典的装箱/拆箱,每次操作都要进行装箱拆箱,很麻烦).
time_t只是64位整型的typedef而已,因此转换为long后,经Swig转换后,对应为java的整型,这样操作起来比较简单
*/
long date_get_time_t(const SDate* d)
{
assert(d);
/*
1、第一版
struct tm date;
//crt函数中year是基于1900年的偏移,因此要减去1900
date.tm_year = d->year - 1900;
//crt函数中月份是[0-11]表示的,我们使用[1-12]表示,因此要减去1
date.tm_mon = d->month - 1;
date.tm_mday = d->day;
date.tm_hour = 0;
date.tm_min = 0;
date.tm_sec = 1;
time_t seconds = mktime(&date);
return (long)seconds;
*/
/*
2、第二版 ios NSCalendar对象计算时间差
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:d->day]; // Monday
[components setMonth:d->month]; // May
[components setYear:d->year];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:components];
return (time_t) [date timeIntervalSince1970];
*/
/*
3、网上Linux版本
*/
return mymktime(d->year,d->month,d->day,0,0,1);
}
/*
blf: 根据delta计算月份,返回值存储在date结构中
例如:当前年月为2015年1月份,delta为2,则返回2014年11月
*/
void date_get_prev_month(SDate* date, int delta)
{
assert(date);
if((date->month - delta) < 1)
{
//条件: 假设为2015年1月,delta = 2
//因为: 1-2 = -1 < 1
//所以: 年数 = 2015 - 1 = 2014 月份 = 12 + 1 - 2 = 11
date->year--;
date->month = 12 + date->month - delta;
}
else
date->month = date->month - delta;
}
/*
blf: 根据delta计算出月份,返回值存储在date结构中
例如:当前年月为2015年11月份,delta为2,则返回2016年1月
*/
void date_get_next_month(SDate* date, int delta)
{
assert(date);
if((date->month + delta) > 12)
{
//条件: 假设为2015年11月,delta = 2
//因为: 11 + 2 = 13 > 12
//所以: 年数 = 2015 + 1 = 2016 月份 = 11 + 2 - 12 = 1
date->year++;
date->month = date->month + delta - 12;
}
else
date->month = date->month + delta;
}
/*
blf: 根据输入年份,判断是否是闰年
固定算法:判断闰年的方法是该年能被4整除并且不能被100整除,或者是可以被400整除
*/
int date_get_leap(int year)
{
if(((year % 4 == 0) && (year % 100) != 0) (year % 400 == 0))
return 1;
return 0;
}
/*
blf: 辅助函数,用于计算某年某月的某天是星期几
*/
int date_get_days(const SDate* date)
{
assert(date);
int day_table[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int i = 0, total = 0;
for(i = 0; i < date->month; i++)
total += day_table[i];
return total + date->day + date_get_leap(date->year);
}
/*
blf: 用于计算某年某月的某天是星期几,调用上面函数
这些算法比较固定,具体原理也不需要太了解,因为我也不清楚。
*/
int date_get_week(const SDate* date)
{
assert(date);
return ((date->year - 1 + (date->year - 1) / 4 - (date->year - 1) / 100 +
(date->year - 1) / 400 + date_get_days(date) )% 7);
}
/*
blf: 用于计算某个月的天数
*/
int date_get_month_of_day(int year, int month)
{
switch(month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12: return 31;
case 4:
case 6:
case 9:
case 11: return 30;
}
//blf:2月比较特别,要进行闰年判断
return 28 + date_get_leap(year);
}
点击查看更多内容
3人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
相关文章推荐
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦