[toc]

场景

时间有三种类型:

1、长期

2、具体时间范围

3、周几展示

解决方案

1、长期:使用bool

2、具体范围:startTime-endTime

3、周几展示:使用二进制为1表示周几,例如:0001011表示周一、周二、周四转为十进制为:11,然后将11存储到数据库中,即可。

长期

对于长期展示为true, false则需要在具体时间范围和周几展示选择其一,最后返回true -> 长期

范围

范围使用两个字段:startTime和endTime,返回直接拼接字符串:startTime-endTime

周几

周几展示由于是在数据库中使用二进制逻辑,然后存储十进制,非常节省空间最大的数127,即:周一到周日都需要展示,这里最重要的也就是应用层需要判断前端参数数组:[1,2,4],转为-> 11然后存储,最后需要将11 -> :[1,2,3,4] 然后 1 -> 周一….

解决方案:

// setDayOfWeek 使用二进制位运算将选择的周几表示为一个整数
func setDayOfWeek(days ...int) uint8 {
	var result uint8
	for _, day := range days {
		result |= (1 << uint(day-1))
	}
	return result
}

// getSelectedDays 将整数表示的选择转换为对应的周几
func getSelectedDays(weekDays uint8) []int {
	var result []int
	for i := 1; i <= 7; i++ {
		if weekDays&(1<<(uint(i-1))) > 0 {
			result = append(result, i)
		}
	}
	return result
}

精准查询

如果我们查询某一个的具体的时间,例如:2023-07-30,属于长期展示的肯定需要查询到的,在展示时间范围的也内的也能够查询到:

select * from coupert_base.store_trending where (IsPermanent = true or '2023-08-30' BETWEEN StartDate AND EndDate) order by `Rank` desc LIMIT 0, 100;

但是我们要查询周几展示应该怎么做?

解决方案:

数据库存储的是标记周几的二进制逻辑的十进制数,我们首先需要将2023-07-30转为我们的周几:这天是周末,也就是:7, 然后我们需要将7转为表示二进制的数:1000000, 然后再将其转为十进制,即:64, 然后就可以使用二进制的&运算, SQL如下:

select * from coupert_base.store_trending where (IsPermanent = true or DayOfWeek & 64 = 64 or '2023-07-30' BETWEEN StartDate AND EndDate) order by `Rank` desc LIMIT 0, 100;

这样就可以查询到符合周日的记录了

转换逻辑代码:

package main

import (
	"fmt"
	"time"
)

// WeekdayToNumber 将 time.Weekday 类型转换为数字周几
func WeekdayToNumber(weekday string) int {
	// 注意:time.Weekday 类型的值从 0(周日)到 6(周六)
	// 我们将其转换为数字周几(1 表示周一,2 表示周二,...,7 表示周日)
	layout := "2006-01-02 15:04:05"
	t, _ := time.Parse(layout, weekday)
	if int(t.Weekday()) == 0 {
		return 7
	}
	return int(t.Weekday())
}

// 查询是否包含指定的二进制值 对应SQL的代码:DayOfWeek & 64 = 64
func containsBinary(target int, value int) bool {
	return target&value == value
}

func main() {
	weekDay := WeekdayToNumber("2023-07-30 00:00:00")
	fmt.Println("周几:", weekDay)
	queryValue := 1 << (weekDay - 1)
	fmt.Println("转为二进制逻辑的数::", queryValue)
	if containsBinary(75, queryValue) { //75 -> 1001011 表示:"周一 周二 周四 周日"
		fmt.Printf("星期%d在记录中", weekDay)
	}
    //输出:
	//周几: 7
	//转为二进制逻辑的数:: 64
    //星期7在记录中
}