JE

 view release on metacpan or  search on metacpan

lib/JE/Object/Date.pm  view on Meta::CPAN

	
	($tmp, $time) = _div $time, MS_PER_DAY * 365;
	# Same special case we encountered when dividing qcms, since there
	# is an extra day on the end.
	if($tmp == 4) {
		return $prec + 4 + 2000;
	}
	$prec + 2000 + $tmp +    # Add 1 if we are past Dec.:
		($time >= (31+30+31+30+31+31+30+31+30+31) * MS_PER_DAY);
		           # days from Mar 1 to Jan 1
}
sub _in_leap_year($) { _days_in_year &_year_from_time == 366 }
sub _day_within_year($) { &_day - _day_from_year &_year_from_time }
sub _month_from_time($) {
	my $dwy = &_day_within_year;
	my $ily = &_in_leap_year;
	return 0 if $dwy < 31;
	my $counter = 1;
	for (qw/59 90 120 151 181 212 243 273 304 334 365/) {
		return $counter if $dwy < $_ + $ily;
		++$counter;
	}
}
sub _date_from_time($) {
	my $dwy = &_day_within_year;
	my $mft = &_month_from_time;
	return $dwy+1 unless $mft;
	return $dwy-30 if $mft == 1;
	return $dwy - qw/0 0 58 89 119 150 180 211 242 272 303 333/[$mft]
		- &_in_leap_year;
}
sub _week_day($) { (&_day + 4) % 7 }

# $_dumdeedum[0] will contain the nearest non-leap-year that begins on Sun-
# day, $_dumdeedum[1] the nearest beginning on Monday, etc.
# @_dumdeedum[7..15] are for leap years.
# For the life of me I can't think of a name for this array!
{
	my @_dumdeedum; 

	my $this_year = (gmtime(my $time = time))[5]+1900;
	$_dumdeedum[_week_day(_time_from_year _year_from_time $time*1000) +
		7 * (_days_in_year($this_year)==366) ] = $this_year;

	my $next_past = my $next_future = $this_year;
	my $count = 1; my $index;
	while ($count < 14) {
		$index = (_day_from_year(--$next_past) + 4) % 7 +
			7 * (_days_in_year($next_past)==366);
		unless (defined $_dumdeedum[$index]) {
			$_dumdeedum[$index] = $next_past;
			++$count;
		}
		$index = (_day_from_year(++$next_future) + 4) % 7 +
			7 * (_days_in_year($next_future)==366);
		unless (defined $_dumdeedum[$index]) {
			$_dumdeedum[$index] = $next_future;
			++$count;
		}
	}
# The spec requires that the same formula for daylight savings be used for
# all years.  An ECMAScript implementation is not  allowed  to  take  into
# account that the formula might have changed in the past. That's what the
# @_dumdeedum array is for. The spec basically allows for fourteen differ-
# ent possibilities for the dates for daylight savings time  change.  The
# code above collects the 'nearest' fourteen years that are not equivalent
# to each other.

	sub _ds_time_adjust($) {
		my $year = _year_from_time(my $time = $_[0]);
		my $ddd_index = (_day_from_year($year) + 4) % 7 +
				7 * (_days_in_year $year == 366);
		my $time_within_year = $time - _time_from_year $year;
		(localtime
		  +(
		    $time_within_year +
		    _time_from_year $_dumdeedum[$ddd_index]
		  ) / 1000 # convert to seconds
		  + EPOCH_OFFSET
		)[8] * 3600_000
	}
}

sub _gm2local($) {
	# shortcut for nan & inf to avoid localtime(nan) warning
	return $_[0] unless $_[0] == $_[0] and $_[0]+1 != $_[0];

	$_[0] + LOCAL_TZA + &_ds_time_adjust
}

sub _local2gm($) {
	# shortcut for nan & inf to avoid localtime(nan) warning
	return $_[0] unless $_[0] == $_[0] and $_[0]+1 != $_[0];

	$_[0] - LOCAL_TZA - _ds_time_adjust $_[0] - LOCAL_TZA
}

sub _hours_from_time($) { floor($_[0] / 3600_000) % 24 }
sub _min_from_time($) { floor($_[0] / 60_000) % 60 }
sub _sec_from_time($) { floor($_[0] / 1000) % 60 }
sub _ms_from_time($) { $_[0] % 1000 }

sub _make_time($$$$) {
	my ($hour, $min, $sec, $ms) = @_;
	for(\($hour, $min, $sec, $ms)) {
		$$_ + 1 == $$_ or $$_ != $$_ and return sin 9**9**9;
		$$_ = int $$_; # ~~~ Is this necessary? Is it sufficient?
	}
	$hour * 3600_000 +
	$min  *   60_000 +
	$sec  *     1000 +
	$ms;
}

sub _make_day($$$) {
	my ($year, $month, $date) = @_;
	for(\($year, $month, $date)) {
		$$_ + 1 == $$_ or $$_ != $$_ and return sin 9**9**9;
		$$_ = int $$_; # ~~~ Is it sufficient?
	}
	$year += floor($month/12);
	$month %= 12;
	_timegm(0,0,0,$date,$month,$year)



( run in 1.247 second using v1.01-cache-2.11-cpan-2398b32b56e )