mtjs / 算法 / 计算月份天数的公式



2014-12-06  mtjs

A Formula for the Number of Days in Each Month

Posted on   |  by  Curtis McEnroe

Recently, after being awake for longer than I should have, I started thinking about methods of remembering the number of days in each month of the year. There is a rhyme for it, and a way to count on your knuckles, but these didn’t satisfy me. I wondered if there was a mathematical formula for the problem, and upon not immediately finding one, I challenged myself to create one.

Put more formally, the challenge was this: find a function f, such that f(x) is equal to the number of days in month x, represented by the integers 1 through 12. Or, as a table of values:1


If you want to give this challenge a go before reading my solution, now is your chance. If you’d rather see my complete solution right away, scroll to the bottom of the page. What follows is my process for solving the problem.

The Tools

Firstly, here’s a quick refresher on two operations I found vital to solving the problem: floor division and modulo.

Floor division is the operation performed by many programming languages when dividing two integer numbers, that is, the result of the division is truncated to the integer part. I will represent floor division as ab, for example:

53 = 1

Modulo is an operation that results in the remainder of a division. It is represented in many programming languages with the% operator. I will represent it as a mod b, for example:

3 mod 2 = 1

Note that modulo has the same precedence as division.

The Basics

With those tools in mind, let’s get a basic pattern going.2 Months usually alternate between lengths of 30 and 31 days. We can use x mod 2 to get an alternating pattern of 1 and 0, then just add our constant base number of days:

f(x) = 30 + x mod 2


That’s a pretty good start! We’ve already got January and March through July done. February is its own special problem we’ll deal with later. The problem after July is that the pattern should skip one, and the rest of the months should follow the alternating pattern inversely.

To obtain an inverse pattern of alternating 0 and 1, we can add 1 to our dividend:

f(x) = 30 + (x + 1) mod 2


Now we have August through December right, but the rest of the year is wrong as expected. Let’s see how we can combine combine our two formulas.


What we need here is basically a piece-wise function, but that’s just no fun. The challenge is to create a single formula. This got me thinking of other ways to use a part of a function only over a certain domain.

I figured the easiest way to do this would be to find an expression equal to 1 over the desired domain and 0 otherwise. Multiplying a term by this expression will result in the term being cancelled out outside its domain. I’ve called this “masking,” since it involves creating a sort of bit-mask.

To mask the latter piece of our function, we need an expression equal to 1 where 8 ≤ x ≤ 12. Floor division by 8 is perfect for this, since all our values are less than 16.


Now if we substitute this expression in our x + 1 dividend, we can invert the pattern using our mask:

f(x) = 30 + (x + ?x8) mod 2


Woot! Everything is correct except February. What a surprise.


Every month has either 30 or 31 days, but February has 28 (leap years are out of scope).3 February currently has 30 days according to our formula, so an expression equal to 2 when x = 2 would be ideal for subtraction.

The best I could come up with was 2 mod x, which gives us a sort of mask over every month after February.

2 mod x002222222222

With this, we’ll need to change our base constant to 28 so that adding 2 to the rest of the months will still be correct.

f(x) = 28 + (x + ?x8) mod 2 + 2 mod x


Unfortunately, January is now 2 days short. Luckily, finding an expression that will apply to only the first month is easy: floored inverse of x. Now just multiply that by 2 and we get the final formula:

f(x) = 28 + (x + ?x8) mod 2 + 2 mod x + 2 ?1x



There you have it, a formula for the number of days in each month using simple arithmetic. So next time you find yourself wondering how many days are in September, just remember to apply f(9). For ease of use, here’s a JavaScript one-liner:

function f(x) { return 28 + (x + Math.floor(x/8)) % 2 + 2 % x + 2 * Math.floor(1/x); }
  1. Naturally, I didn’t feel like using any of the mnemonics, so I looked this table up on the Internet.
  2. “The Basics,” or, “The Rule With Many Exceptions,” like most rules.
  3. February was originally the last month of the year in the Roman calendar, so it actually makes more sense than it seems for it to be shorter than the others. It also makes more sense that its length would vary, since adding or removing a day from the end of the year is more intuitive.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。如发现有害或侵权内容,请点击这里 或 拨打24小时举报电话:4000070609 与我们联系。

    来自: mtjs > 《算法》



    请遵守用户 评论公约

    喜欢该文的人也喜欢 更多