
- 问题1:什么叫做连续签到天数?
从最后一次签到向前统计,直到遇到第一次未签到为止,计算总的签到次数,就是连续签到天数。
- 问题2:如何得到本月到今天为止的所有签到数据?
BITFIELD key GET u[dayOfMonth] 0 //从0开始,统计dayOfMonth天 例1:BITFIELD key GET u1 0 // 从0开始,统计1天 例2:BITFIELD key GET u2 0 // 从0开始,统计2天 例3:BITFIELD key GET u2 0 // 从0开始,统计3天
- 问题3:如何从后向前遍历每个bit位?
将返回整数与1做与运算,就能得到最后一个bit位状态。随后将整数右移1位,下一位bit位就成为最后一个bit位了,直到遍历到从右往左数第一个为0的位置
- 统计截至今日的连续签到次数
java
/**
* 统计当前用户连续签到天数。
*
* 作用:
* 1.获取当前登录用户;
* 2.获取日期;
* 3.拼接key;
* 4.获取今天是本月的第几天;
* 5.获取本月截至今天为止的所有的签到记录,返回的是一个十进制的数字BITFIELDsig;
*
* @return处理结果
*/
@Override
public Result signCount() {
//1.获取当前登录用户
Long userId = UserHolder.getUser().getId();
//2.获取日期
LocalDateTime now = LocalDateTime.now();
//3.拼接key
String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
String key = USER_SIGN_KEY + userId + keySuffix;
//4.获取今天是本月的第几天
int dayOfMonth = now.getDayOfMonth();
//5.获取本月截至今天为止的所有的签到记录,返回的是一个十进制的数字BITFIELD sign:5:202203 GET u14 0
List<Long> result = stringRedisTemplate.opsForValue()
.bitField(key, BitFieldSubCommands.create() //创建BITFIELD子命令对象
.get(BitFieldSubCommands //对应Redis里的GET
.BitFieldType.unsigned(dayOfMonth)).valueAt(0)); //读取dayofmonth个bit,并且把它当成无符号整数,valueAT(0)表示从0位开始读
if (result == null || result.isEmpty()) {
//没有任何签到结果
return Result.ok(0);
}
Long num = result.get(0);
if (num == null || num == 0) {
return Result.ok(0);
}
//6.循环遍历
int count = 0;
while (true) {
//6.1.让这个数字与1做与运算,得到数字的最后一个bit位 //判断这个bit位是否为0
if ((num & 1) == 0) {
//如果为0,说明未签到,结束
break;
} else {
//如果不为0,说明已签到,计数器+1
count++;
}
//把数字右移一位,抛弃最后一个bit位,继续下一个bit位
num >>>= 1;
}
return Result.ok(count);
}