<?php
#https://xie.infoq.cn/article/9b0827c018443828d2f0ebedf
#https://www.bbsmax.com/A/lk5aQwbZ51/
#https://www.php.cn/php-weizijiaocheng-387074.html
#setbit u:sign:1000:202108 17 1
               uid:month day 1                
/*
127.0.0.1:6379> setbit u:sign:1000:202108 17 1
(integer) 0
127.0.0.1:6379> setbit u:sign:1000:202108 16 1
(integer) 0
127.0.0.1:6379> bitcount u:sign:1000:202108
(integer) 2
127.0.0.1:6379> bitfield u:sign:1000:202108 get u31 0
1) (integer) 24576
127.0.0.1:6379> setbit u:sign:1000:202108 15 1
(integer) 0
127.0.0.1:6379> bitfield u:sign:1000:202108 get u31 0
1) (integer) 57344
127.0.0.1:6379> setbit u:sign:1000:202108 0 1
(integer) 0
127.0.0.1:6379> setbit u:sign:1000:202108 1 1
(integer) 0
127.0.0.1:6379> setbit u:sign:1000:202108 5 1
(integer) 0
127.0.0.1:6379> bitfield u:sign:1000:202108 get u31 0
1) (integer) 1644224512
127.0.0.1:6379>
*/

#每月签到信息
$days = 31;
// bitfield u:sign:1000:202108 get u31 0
$result = 1644224512;//每set一次都需要改变一下这个值
$list = [];
// 从低位到高位遍历,0表示未签到;1表示已签到
for ($i = $days; $i > 0; $i--) {
    // 本月已经循环完直接退出
    if ($i < 0) break;
    // 定义当前的日期是多少
    $local_date = date('Y-m') . '-' . $i;
    
    // 右移再左移,如果不等于自己说明最低位是 1,表示已签到 
    $flag = (($result >> 1 << 1) != $result) ? true : false;
    
     // 如果已签到,添加标记为1,否则为0
    $list[$local_date] = $flag ? 1 : 0;
    
     // 然后右移一位重新赋值计算
    $result >>= 1;
}

var_dump($list);


// 假设今天18号,获取连续签到日
$days = 18;
$signCount = 0;
// bitfield u:sign:1000:202108 get u18 0
$value = 200711;
for ($i = $days; $i > 0; $i--) {
    if ($i < 0) break;

    if (($value >> 1 << 1) == $value) {
        if ($i != $days){
            break;
        }
    } else {
        $signCount++;
    }

    $value >>= 1;
}

var_dump($signCount);