【签到】实现签到功能

BitMap用法

Redis中是利用string类型数据结构实现BitMap,因此最大上限是512M,转换为bit则是2^32个bit位。

BitMap的操作命令有:

  • SETBIT:向指定位置( offset)存入一个0或1
  • GETBIT:获取指定位置( offset)的bit值
  • BITCOUNT:统计BitMap中值为1的bit位的数量公
  • BITFIELD∶操作(查询、修改、自增)BitMap中bit数组中的指定位置(offset)的值
  • BITFIELD_RO∶获取BitMap中bit数组,并以十进制形式返回
  • BITOP∶将多个BitMap的结果做位运算(与、或、异或)
  • BITPOS:查找bit数组中指定范围内第一个0或1出现的位置

Java伪代码

获取连续签到数

    @Override
    public Result signCount() {
        //1  获取当前用户
        UserDTO user = UserHolder.getUser();
        //2  获取日期
        LocalDateTime now = LocalDateTime.now();
        //3 拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyy/MM"));
        String key = "sign:"+user.getId() + keySuffix ;

        //4 获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        //5 获取本月截止今天为止的所有的签到记录 返回的一个十进制的数字 BITFIELD sign:1:2022/08 GET u21 0
        List<Long> result = stringRedisTemplate.opsForValue()
                .bitField(key,
                        BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));
        //6 循环遍历
        if (result == null || result.isEmpty())
        {
            return Result.ok();
        }
        Long num = result.get(0);
        if (num == null || num == 0){
            return Result.ok();
        }
        int count = 0;
        log.debug("s{}"+num);
        String s = Integer.toBinaryString(num.intValue());
        System.out.println(s);
        while (true){
            //7  让这个数字与1做与运算,得到数字最后一个bit位
            //判断这个bit位是否为0
            if ((num & 1) == 0) {
                //如果为0,说明未签到,结束
                break;
            }else {
                count++;
            //如果不为0,说明已签到,计数器+1
            }
            //把数字右移一位,抛弃最后一个bit位,继续下一个bit位
            num >>>= 1 ;
        }
        return Result.ok(count);
    }

获取当前月签到情况

    //获取当前月的签到情况
    @Test
    public void sing1(){
        //2  获取日期
        LocalDate now = LocalDate.now();
        Map<String, Boolean> signMap = new HashMap<>(now.getDayOfMonth());
        //3 拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern("yyyy/MM"));
        String key = "sign:1:" + keySuffix ;

        // 获取本月有多少天
        Integer days =now.lengthOfMonth();
        List<Long> result = stringRedisTemplate.opsForValue()
                .bitField(key,
                        BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(days)).valueAt(0));
        //6 循环遍历
        if (result == null || result.isEmpty())
        {return ;
        }
        Long num = result.get(0);
        if (num == null || num == 0){
            return ;
        }
        for (int i = now.lengthOfMonth(); i > 0; i--) {
            LocalDate d = now.withDayOfMonth(i);
            if ((num & 1) == 0) {
                //如果为0,说明未签到,结束
                signMap.put(d.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), false);
            }else {
                //如果不为0,说明已签到,计数器+1
                signMap.put(d.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), true);
            }
            //把数字右移一位,抛弃最后一个bit位,继续下一个bit位
            num >>>= 1 ;
        }
        System.out.println("当月签到情况:");
        for (Map.Entry<String, Boolean> entry : signMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + (entry.getValue() ? "√" : "-"));
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值