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

Posted

技术标签:

【中文标题】使用按位运算从 int 日期中提取月份 (yyyyMMdd)【英文标题】:using bitwise operation to extract month from int date (yyyyMMdd) 【发布时间】:2012-06-13 21:41:55 【问题描述】:

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

如果可以,怎么办?

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

【问题讨论】:

虽然您可以使用按位运算来完成,但为此使用数学运算更容易。 仅有的两个可能答案是“是”或“否”。这真的是您想要的吗? 为什么必须使用按位运算?对于您要访问的内容,这似乎过于复杂且不必要。您似乎还列出了三种不同的语言标签,您使用的是什么语言?例如,C# 已经为此内置了方法。 答案是是的,虽然并不直截了当。所有算术运算都可以通过位运算来实现。 我目前正在使用 20110401 % 10000 / 100。认为按位可能会更快。没有? 【参考方案1】:

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

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

int date = 20110401;

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

【讨论】:

如果使用 C#,则解析为 DateTime ;) 当然有可能,因为计算机是在电路级别进行按位运算,但在软件中尝试模拟这些是没有意义的。 "您的日期使用十进制表示。" ——但有必要吗?请参阅下面的答案。 或者你可以使用一个包含一个短字节和两个字节的结构。 可以,但将日期编码为 int 可能更容易一些。【参考方案2】:

20110301(以 10 为基数)作为整数在位级别的表示方式完全不同,实际上是 1001100101101101111011101(以 2 为基数)。使用位级操作从这个位串中提取月份并不是一件容易的事。

替代方案:

对整数做一些涉及 mod 的基本数学运算

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

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

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

【讨论】:

【参考方案3】:

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

您也可以将其转换为字符串,解析月份字符,然后再转换回 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));

【讨论】:

【参考方案4】:

如果您以二进制格式表示日期,则可以通过按位运算有效地提取月份,例如,5 位表示月份的日期,4 位表示月份编号,其余部分年份,而不是十进制数字。对于您的示例,日期将是 (2011

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 ;

【讨论】:

【参考方案5】:

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

    //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;
    

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

【讨论】:

以上是关于使用按位运算从 int 日期中提取月份 (yyyyMMdd)的主要内容,如果未能解决你的问题,请参考以下文章

从日期字段中减去月份并提取run yr mo的逻辑

使用整数字段通过按位运算存储选定的日期

网络套件!使用 freemarker 从日期 DD/MM/YYYY 获取月份名称不起作用

昨天如何从Date()中提取今天,并将其定位为工作日和月份?

如何根据日期获取月份的天数?

在 C++ 中使用 atoi 将 char 数组转换为 int 值