В основном, я пытаюсь воссоздать функциональность года в формате PHP. Используя количество секунд с 1 января 1970 года, я пытаюсь получить год с помощью встроенной функции. У меня была идея, но она не работала из-за високосных лет. Может ли кто-нибудь дать мне рабочую формулу, которая занимает секунды с 1970 года и получает год от нее?
Чтобы найти год, вам нужно справиться с прыжками.
Годы от 1 заказываются, поскольку блоки из 4 лет являются последними из них на один день дольше, не так ли? Таким образом, у вас есть блоки:
seconds_block = 365*3 + 366 days = 126230400 seconds seconds_year = 365 days = 31536000 seconds
1970 год является вторым годом его блока, поэтому:
<?php //test_year.php $given_seconds = $argv[1]; $seconds_year = 31536000; $seconds_block = 126230400; $total_blocks_to_1968 = 492; $actual_block = floor((($given_seconds + $seconds_year) / $seconds_block)) + $total_blocks_to_1968; $actual_offset_from_last_block = ($given_seconds + $seconds_year) % $seconds_block; $actual_year_of_the_block = min(floor($actual_offset_from_last_block / $seconds_year) + 1, 4); $actual_year = $actual_block * 4 + $actual_year_of_the_block; echo $actual_year;
Тестирование этого …
$ php test_year.php 0 1970 $ php test_year.php 1 1970 $ php test_year.php -1 1969 $ php test_year.php 31536000 1971 $ php test_year.php 31535999 1970 $ php test_year.php 126230400 1974 $ php test_year.php 126230399 1973
Подробнее: Один год – прыжок, если он делится на 4, за исключением тех, которые делятся на 100 (но не на 400).
function isLeap(year){ return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0) }
EDIT: псевдокодная формула
x = input // number of seconds since 1970 sy = 31536000 // seconds a non leap year sb = 126230400 // seconds a block of 3 non leap years and one that is actual_year = (floor(((x + sy) / sb)) + 492) * 4 + (min(floor(((x + sy) % sb) / sy) + 1, 4));
ура
Вы не можете игнорировать високосные годы.
Кроме того, год прыгает, если – если заканчивается 00, если он не дает покоя после деления на 400 – иначе, если он не дает покоя после деления на 4
Вы определяете код 🙂
И да, это не очень оптимизировано 🙂
ps, очевидно, когда месяц за месяцем, имейте в виду, что февраль имеет 29 дней, если год скачок 🙂
Это на самом деле неправильно, но достаточно хорошее приближение, если вам не нужен год, чтобы точно измениться в момент нового года. Идея состоит в том, что количество дней в году, чтобы быть високосным годами каждые 4 года, составляет 365,25 дня.
$a = time(); $y = 1970 + floor($a / 60 / 60 / 24 / 365.25);
Если вы используете UNIX-подобную систему, вы можете использовать функциональность date
системы для форматирования времени вместо переопределения функции PHP:
date +%Y
дает текущий год. Затем вы можете использовать ключ -d для форматирования пользовательской даты, а не текущей даты:
date -d "UTC 1970-01-01 1287946333 secs +%Y"
дает «2010».
В течение 1970-1920 годов вы можете использовать эти эквиваленты (+/- несколько минут для месяцев и лет):
Human readable time Seconds 1 minute 60 seconds 1 hour 3600 seconds 1 day 86400 seconds 1 week 604800 seconds 1 month (30.44 days) 2629743 seconds 1 year (365.24 days) 31556926 seconds
Вы можете проверить свои формулы здесь. Эти эквиваленты могут быть отключены на достаточное количество минут в ключевые дни (например, 31 декабря / 1 января) и хороши только в эпоху от границ.
Если вы хотите быть точным, вам нужно иметь дело с каждым високосным годом; либо через формулу, либо через итерацию.
Этот код Perl вычисляет год с периодов эпохи за любой год +/- 130 или более лет с 1970 года (эпоха Unix). Вы должны знать на своей платформе, как большой (32-разрядный или 64-разрядный) номер эпохи должен знать диапазон:
sub days_in_year { my $year=shift; my $leap = ($year % 400 == 0) ? 1 : ($year % 100 == 0) ? 0 : ($year % 4 == 0) ? 1 : 0 ; return (365+$leap); } sub epoch_to_year { use integer; my $t=shift; my $ey=1970; my $secs=$t; if($t<0) { while($secs<0) { $secs+=days_in_year(--$ey)*24*60*60; } return $ey; } else { while($secs>0) { $secs-=days_in_year($ey++)*24*60*60; } return $ey if ($secs==0); return $ey-1; } }
Это МЕДЛЕННО, и вы должны использовать библиотеку, но у вас ее нет, она будет работать. Тривиально перевести это на PHP. ( sub
=> function
, delete my
и т. д.)