Skip to content
DAILY QUOTE

“ ”

  • 问题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);
}