Calculate day number from an unix-timestamp in a math way?

后端 未结 3 2004
一整个雨季
一整个雨季 2021-01-12 08:13

How can i calculate day number from a unix-timestamp, in a mathematical way and without using any functions and in simple math formula.

1313905026 --> 8 (Today 08/21

3条回答
  •  感情败类
    2021-01-12 08:49

    A unix timestamp doesn't include leap seconds, so we don't have to worry about that. Here is a branch-less1, loop-less algorithm for getting the y/m/d fields from a unix timestamp:

    #include 
    
    int
    main()
    {
        int s = 1313905026;
        int z = s / 86400 + 719468;
        int era = (z >= 0 ? z : z - 146096) / 146097;
        unsigned doe = static_cast(z - era * 146097);
        unsigned yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365;
        int y = static_cast(yoe) + era * 400;
        unsigned doy = doe - (365*yoe + yoe/4 - yoe/100);
        unsigned mp = (5*doy + 2)/153;
        unsigned d = doy - (153*mp+2)/5 + 1;
        unsigned m = mp + (mp < 10 ? 3 : -9);
        y += (m <= 2);
        std::cout << m << '/' << d << '/' << y << '\n'; // 8/21/2011
    }
    

    This outputs:

    8/21/2011
    

    As you're not interested in y and m (only in d), you can eliminate the last couple of lines from the above computation.

    This algorithm is described in excruciating detail here. The link includes a complete derivation, and unit tests spanning millions of years (which is overkill).


    1 Branch-less: What looks like small branches in the algorithm above are optimized away by clang at -O3 on macOS:

    __Z14get_day_numberi:                   ## @_Z14get_day_numberi
        .cfi_startproc
    ## BB#0:
        pushq   %rbp
    Ltmp0:
        .cfi_def_cfa_offset 16
    Ltmp1:
        .cfi_offset %rbp, -16
        movq    %rsp, %rbp
    Ltmp2:
        .cfi_def_cfa_register %rbp
        movslq  %edi, %rax
        imulq   $-1037155065, %rax, %rcx ## imm = 0xFFFFFFFFC22E4507
        shrq    $32, %rcx
        addl    %ecx, %eax
        movl    %eax, %ecx
        shrl    $31, %ecx
        sarl    $16, %eax
        leal    (%rax,%rcx), %edx
        leal    719468(%rax,%rcx), %esi
        testl   %esi, %esi
        leal    573372(%rax,%rcx), %eax
        cmovnsl %esi, %eax
        cltq
        imulq   $963315389, %rax, %rcx  ## imm = 0x396B06BD
        movq    %rcx, %rsi
        shrq    $63, %rsi
        shrq    $32, %rcx
        sarl    $15, %ecx
        addl    %esi, %ecx
        imull   $146097, %ecx, %ecx     ## imm = 0x23AB1
        movl    %eax, %esi
        subl    %ecx, %esi
        subl    %eax, %esi
        leal    719468(%rsi,%rdx), %eax
        movl    %eax, %ecx
        shrl    $2, %ecx
        imulq   $1506180313, %rcx, %rdx ## imm = 0x59C67CD9
        shrq    $39, %rdx
        movl    %eax, %esi
        subl    %edx, %esi
        imulq   $963321983, %rcx, %rcx  ## imm = 0x396B207F
        shrq    $43, %rcx
        addl    %esi, %ecx
        movl    %eax, %edx
        shrl    $4, %edx
        imulq   $7525953, %rdx, %rdx    ## imm = 0x72D641
        shrq    $36, %rdx
        subl    %edx, %ecx
        imulq   $1729753953, %rcx, %rsi ## imm = 0x6719F361
        shrq    $32, %rsi
        movl    %ecx, %r8d
        subl    %ecx, %eax
        movl    %ecx, %edi
        movl    $3855821599, %edx       ## imm = 0xE5D32B1F
        imulq   %rcx, %rdx
        subl    %esi, %ecx
        shrl    %ecx
        addl    %esi, %ecx
        shrl    $8, %ecx
        imull   $365, %ecx, %ecx        ## imm = 0x16D
        subl    %ecx, %r8d
        shrl    $2, %edi
        imulq   $1506180313, %rdi, %rcx ## imm = 0x59C67CD9
        shrq    $39, %rcx
        shrq    $47, %rdx
        addl    %r8d, %eax
        subl    %ecx, %eax
        leal    (%rax,%rdx), %ecx
        leal    2(%rcx,%rcx,4), %esi
        movl    $3593175255, %edi       ## imm = 0xD62B80D7
        imulq   %rsi, %rdi
        shrq    $39, %rdi
        imull   $153, %edi, %edi
        subl    %edi, %esi
        leal    4(%rcx,%rcx,4), %ecx
        subl    %esi, %ecx
        movl    $3435973837, %esi       ## imm = 0xCCCCCCCD
        imulq   %rcx, %rsi
        shrq    $34, %rsi
        leal    1(%rax,%rdx), %eax
        subl    %esi, %eax
        popq    %rbp
        retq
        .cfi_endproc
    

提交回复
热议问题