实现:
1.签到功能的基本实现。
2.统计连续签到的天数
签到功能:
逻辑简单:获取用户和月份天数,然后存入redis;
SETBIT key offset value
/**
* 用户签到
* @return
*/
@Override
public Result sign() {
//先拿到用户和签到对应的日期
Long UserId = UserHolder.getUser().getId();
LocalDateTime now = LocalDateTime.now();
String format = now.format(DateTimeFormatter.ofPattern(":yyyy:MM"));
String key = RedisConstants.USER_SIGN_KEY+UserId+format;
//offset = dayOfMonth:这个月的第几天 。offset从0开始 ,所以存的时候-1
int dayOfMonth = now.getDayOfMonth();
// SETBIT key offset value
stringRedisTemplate.opsForValue().setBit(key,dayOfMonth-1,true);
return Result.ok();
}
获取连续签到天数:
BITFIELD sign:1:2024:02 GET u22 0:来获取本月从第一天到我们签到的第22天的二进制数转化为十进制的结果。举个简单例子,
sign:1:2024:02 = 0000000000000000001011,总长22
那么执行后的结果为:1+2+8=11;
我们用11 去 并 上 1,结果为1:代表签到了,count+1。结果为0,没签到,此时的count就是我们的连续签到天数,break循环即可。签到了,把11的二进制右移动1为,再次 并 上 1重复该循环。
11的二进制:1011,循环第一次,&1不为0,count++=1,右移动,变成 0101,
循环第二次,&1不为0,count++=2,右移动,变成 0010,
循环第二次,&1为0,break,count=2;
所以连续签到天数是2天。
/**
* 本月连续签到天数
* @return
*/
@Override
public Result countForMonuth() {
//先拿到用户和签到对应的日期
Long UserId = UserHolder.getUser().getId();
LocalDateTime now = LocalDateTime.now();
String format = now.format(DateTimeFormatter.ofPattern(":yyyy:MM"));
String key = RedisConstants.USER_SIGN_KEY+UserId+format;
//offset = dayOfMonth:这个月的第几天 。offset从0开始 ,所以存的时候-1
int dayOfMonth = now.getDayOfMonth();
// BITFIELD sign:1:2024:02 GET u22 0
//u是不带单位,22代表查22个,0是从第1个开始
List<Long> longList = stringRedisTemplate.opsForValue().bitField(
key,
BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0)
);
if(longList == null || longList.isEmpty()) {
return Result.ok(0);
}
int count = 0;
Long sum = longList.get(0);
System.out.println(sum);
while (true) {
//与运算 1 与 任何数都等于那个数 为 1 说明签了,0没有
if((sum & 1) == 0) {
break;
} else {
//为1:签过了
count++;
}
//右移动1为在赋值给 sum
sum>>>=1;
}
return Result.ok(count);
}