如何使用位域存储星期几?

How to store days of week using bit field?

我是 re-factoring 一个应用程序,其中一个数据库表将星期几存储在列中。每一天都可以是“开”或“关”。

打开和关闭的概念让我觉得可以将此数据更简洁地表示为位。但是我以前没有使用原始位作为数据类型。

申请是在PHP写的。我见过用于存储 header 值 here 的位。然后有“辅助”常量(HEADER_X_FORWARDED_ALLHEADER_X_FORWARDED_ALL 作为“pre-configurations” 用于 all header 被使用,或 sub-set 用于 AWS ELB-like 环境(其中一些 header 未发送,因此“关闭”)。

所以我有几个问题使用这种数据类型来表示星期几:

  1. 如何将最终位值存储在 MySQL 中?如列数据类型、长度等

  2. 我如何检查某一天是否“开启”?如果我有值 0b0100000,我如何使用 bitwise operators 确定星期二是“开”?

  3. 如何“设置”天数以将值保存在数据库中?因此,如果我在 UI 中有复选框将值作为数组提交,我将如何转换如下内容:

Array
(
    [days] => Array
        (
            [Monday] => 0
            [Tuesday] => 1
            [Wednesday] => 0
            [Thursday] => 0
            [Friday] => 0
            [Saturday] => 0
            [Sunday] => 0
        )
)

…像0b0100000这样的位值,再次使用按位运算符?

如果有人能为我指明开始使用 PHP 中的位值的正确方向,我将不胜感激!

您可以存储所选日期的十进制值。所以作为一个非常基本的例子:

/**
 * Keys are ISO-8601 numeric representation
 * of the days of the week
 */
$days = [
    1 => 0b0000001, // Monday    =>  1
    2 => 0b0000010, // Tuesday   =>  2
    3 => 0b0000100, // Wednesday =>  4
    4 => 0b0001000, // Thursday  =>  8
    5 => 0b0010000, // Friday    => 16
    6 => 0b0100000, // Saturday  => 32
    7 => 0b1000000, // Sunday    => 64
];

您只需循环并检查值中是否设置了当天的位(按位与):

// The value you'd store in your database
$mondayToFriday = 31; // 1 + 2 + 4 + 8 + 16

foreach ($days as $n => $v) {
  
    /**
     * Get the day's name using strftime (has locale capability)
     * strtotime("Sunday +n days") would work with ISO-8601 day
     * numbers or PHP's date("w") (0 - 6 / Sunday - Saturday)
     */
    $day = strftime("%A", strtotime("Sunday +{$n} days"));


    echo "{$day}: " . (($v & $mondayToFriday) ? "Y" : "N") . PHP_EOL;

}

至于您的复选框,您可以根据每天的状态(0 或 1)构建二进制字符串,然后使用 bindec()(它们在数组中出现的顺序)将其转换为十进制很重要,您需要确保它们正确映射到相应日期的值)。

给定您的示例输入以及本示例中的天数,以下内容可行:

$dec = bindec(strrev(implode("", $input["days"])));

希望这会把你推向正确的方向。

Here's an example to play with