使用按位运算从整数日期 (yyyyMMdd) 中提取月份

本文关键字:yyyyMMdd 取月份 提取 日期 整数 运算 | 更新日期: 2023-09-27 18:37:01

是否可以使用一些按位运算符提取表示为int的月份(格式为 YYYYMMDD,例如 20110401)?

如果是这样,怎么能做到?

编辑:我目前正在使用 20110401% 10000/100。我认为按位可以更快。DateTime.Parse等对于我正在尝试做的事情来说太慢了。

使用按位运算从整数日期 (yyyyMMdd) 中提取月份

否,因为按位运算符使用数字的二进制表示形式。您的日期使用十进制表示形式进行编码。

不过,您可以使用算术运算符来做到这一点:

int date = 20110401;
int day = date % 100;
int month = (date / 100) % 100;
int year = date / 10000;
20110301

基数 10)作为整数在位级别表示的方式将大不相同,实际上表示为1001100101101101111011101(基数 2)。使用位级操作从此位字符串中提取月份不会是直截了当的。

选择:

  • 做一些基本的数学运算,涉及整数上的mod

  • int转换为字符串,然后提取相关数字并将其转换回整数。

  • 或者更好的是,为此使用一些已经测试过的库函数。

位级操作不是解决此问题的好方法。

使用按位运算可能容易出错,如果你能做到的话。您可以通过使用除法和模运算操作数字来做到这一点。

您还可以将其转换为字符串,解析月份字符,然后转换回 int。

下面是 C# 中的一些示例代码

int date = 20119420;
int month = 0;
// using good old math
month = (date / 100) % 100;
// using string parsing
month = int.Parse(date.ToString().Substring(4, 2));

如果您以二进制格式表示日期,则可以使用按位运算有效地提取月份,例如,5 位表示月份中的某天,4 位表示月份编号,其余表示年份,而不是十进制数字。例如,日期为 (2011 <<9) + (4 <<5) + 1(当然不等于 20110401)。使用按位运算从此类表示形式中提取字段:

int year = date >> 9;
int month = (date >> 5) & 0xF;
int day = date & 0x1F;

正如Mark Byers所提到的,另一种方法是使用结构体,例如:

typedef struct {
    short year;
    char  month;
    char  day;
} Date;

您可以在堆栈上传递这些字段,按名称提取字段,并将它们初始化为

Date d = { 2011, 4, 1};

或者,在 C99 中,

Date d = { .year = 2011, .month = 4, .day = 1 };

所以我知道这是一个非常古老的帖子,但这实际上是我们类的作业,我有一个压缩日期和一个仅使用按位运算的提取日期函数:

    //Compress Date
    int compressDate(int month, int day, int year)
    {
        int date = year;
        date <<= 4;
        date |= month;
        date <<= 6;
        date |= day;
        return date;
    }
    //Extract Date
    void extractDate(int date, int& month, int& day, int& year)
    {
        int dayMask = 63;
        int monthMask = 15;
        int yearMask = 4095;

        day = date & dayMask;
        date >>= 6;
        month = date & monthMask;
        date >>= 4;
        year = date & yearMask;
    }

当您使用 compileDate(1, 25, 2019) 之类的内容执行压缩日期函数时,它会返回数字:2067545 并且 extractDate 函数以相反的顺序工作。这样做的原因是按位运算符比使用数学运算符更快。