菜鸟教程小白 发表于 2022-12-12 14:38:57

ios - 为什么 NSDate 的 dateWithTimeIntervalSince1970 会修改其输入?


                                            <p><p>我正在运行以下代码:</p>

<pre><code>for (int i = 0; i &lt; 100; ++i) {
NSDate *date = ;
NSTimeInterval interval = date.timeIntervalSince1970;
NSDate *newDate = ;

if (!) {
    NSLog(@&#34;Not equal!&#34;);
}
}
</code></pre>

<p>令人惊讶的是,在许多迭代中,日期并不相等。怎么可能?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>反汇编<code>dateWithTimeIntervalSince1970:</code>显示调用<code>-initWithIntervalSinceReferenceDate:</code>:</p>

<pre><code>CoreFoundation`+:
    0x10fd39430 &lt;+0&gt;:pushq%rbp
    0x10fd39431 &lt;+1&gt;:movq   %rsp, %rbp
    0x10fd39434 &lt;+4&gt;:pushq%rbx
    0x10fd39435 &lt;+5&gt;:pushq%rax
    0x10fd39436 &lt;+6&gt;:movsd%xmm0, -0x10(%rbp)
    0x10fd3943b &lt;+11&gt;: movq   0x2d8146(%rip), %rsi      ; &#34;alloc&#34;
    0x10fd39442 &lt;+18&gt;: movq   0x29edc7(%rip), %rbx      ; (void *)0x000000010f35e940: objc_msgSend
    0x10fd39449 &lt;+25&gt;: callq*%rbx
    0x10fd3944b &lt;+27&gt;: movsd-0x10(%rbp), %xmm0      ; xmm0 = mem,zero
    0x10fd39450 &lt;+32&gt;: addsd0x1f9d58(%rip), %xmm0   ; _CFLog_os_trace_type_map + 16
    0x10fd39458 &lt;+40&gt;: movq   0x2d9041(%rip), %rsi      ; &#34;initWithTimeIntervalSinceReferenceDate:&#34;
    0x10fd3945f &lt;+47&gt;: movq   %rax, %rdi
    0x10fd39462 &lt;+50&gt;: callq*%rbx
    0x10fd39464 &lt;+52&gt;: movq   0x2d81b5(%rip), %rsi      ; &#34;autorelease&#34;
    0x10fd3946b &lt;+59&gt;: movq   %rax, %rdi
    0x10fd3946e &lt;+62&gt;: movq   %rbx, %rax
    0x10fd39471 &lt;+65&gt;: addq   $0x8, %rsp
    0x10fd39475 &lt;+69&gt;: popq   %rbx
    0x10fd39476 &lt;+70&gt;: popq   %rbp
    0x10fd39477 &lt;+71&gt;: jmpq   *%rax
    0x10fd39479 &lt;+73&gt;: nopl   (%rax)
</code></pre>

<p>此外,初始化程序的输入是 <code>secs - 978307200</code>(或 <code>secs - NSTimeIntervalSince1970</code>),即 1970 年与引用日期之间的时间差。这种计算虽然从 double 中减去整数( double ),但由于舍入误差,可能会更改输入值的分数。例如,这是一个未通过测试的日期:</p>

<pre><code>date: Sun Mar 25 17:54:39 2018 (543682479.8504179716),
newDate: Sun Mar 25 17:54:39 2018 (543682479.8504180908)
</code></pre>

<p>由于 <code>log2(543682479.8504179716 + NSTimeIntervalSince1970) ~ 30.5</code> 和 <code>log2(543682479.8504179716) ~ 29.01</code> 需要调整 double 值的指数,尾数需要调整归一化,可能会影响小数值。</p>

<p>解决办法是改用<code>+dateWithTimeIntervalSinceReferenceDate:</code>工厂方法,直接初始化一个<code>NSDate</code>,无需额外计算。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 为什么 NSDate 的 dateWithTimeIntervalSince1970 会修改其输入?,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/49480305/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/49480305/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 为什么 NSDate 的 dateWithTimeIntervalSince1970 会修改其输入?