用户签到相关实现

实现:

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);
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值