New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed wrong counting on leap days #6676
Fixed wrong counting on leap days #6676
Conversation
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed (or fixed any issues), please reply here with What to do if you already signed the CLAIndividual signers
Corporate signers
ℹ️ Googlers: Go here for more info. |
@googlebot I signed it! |
CLAs look good, thanks! ℹ️ Googlers: Go here for more info. |
ruby/ext/google/protobuf_c/upb.c
Outdated
@@ -10124,6 +10124,10 @@ static bool isleap(int year) { | |||
return (year % 4) == 0 && (year % 100 != 0 || (year % 400) == 0); | |||
} | |||
|
|||
static int isleap_count(int year) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
leap_count
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment about what 'year' mean and what the returned value mean
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK! I renamed to leap_count
and added a comment! 💡
6b4224c
ruby/ext/google/protobuf_c/upb.c
Outdated
@@ -10134,7 +10138,7 @@ const unsigned short int __mon_yday[2][13] = { | |||
int64_t epoch(int year, int yday, int hour, int min, int sec) { | |||
int64_t years = year - EPOCH_YEAR; | |||
|
|||
int64_t leap_days = years / 4 - years / 100 + years / 400; | |||
int64_t leap_days = isleap_count(year - 1) - isleap_count(EPOCH_YEAR - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not putting year - 1 into leap_count?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also add a test in
RunValidJsonTest( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not putting year - 1 into leap_count?
static int leap_count(int year)
returns the number of leap days between 1 and year.
Therefore, this logic calculated the number of leap days between 1970
and year - 1
.
The relation between is_leap
and leap_count
is shown below.
is_leap(1) => false
is_leap(2) => false
is_leap(3) => false
is_leap(4) => true
is_leap(5) => false
is_leap(6) => false
is_leap(7) => false
is_leap(8) => true
leap_count(1) => 0
leap_count(2) => 0
leap_count(3) => 0
leap_count(4) => 1
leap_count(5) => 1
leap_count(6) => 1
leap_count(7) => 1
leap_count(8) => 2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also add a test in
OK! I added a new test case!
63837ef
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also port your code to https://github.com/protocolbuffers/upb/blob/d3762e96cb8910b8281419faee7bd70b323c753d/upb/json/parser.rl#L1707
and https://github.com/protocolbuffers/protobuf/blob/master/php/ext/google/protobuf/upb.c#L10137
OK! I ported the same code to php!
3574836
I'll make another PR for https://github.com/protocolbuffers/upb .
I reworked this code a bit for a new JSON parser I have in progress: https://github.com/haberman/upb/blob/4a2b7d721ad8b210fedda33251d30d3eaa235c73/upb/json_parser.c#L1017-L1038 Could you see if the new code fixes the problem? If so, could we use this new, simpler code instead? If the new code doesn't fix the problem, that would be good to know too. |
I created a new PR with the new, simplified code: #6693 |
Sorry for the too late reply 🙇 I also tested the vagrant@vagrant:~/haberman/protobuf/ruby$ git branch
master
* rubyjson2 vagrant@vagrant:~/haberman/protobuf/ruby$ pry
[1] pry(main)> require 'google/protobuf'
=> true
[2] pry(main)> require 'google/protobuf/timestamp_pb'
=> true [3] pry(main)> [*1900..2010].each { |year| t = Google::Protobuf::Timestamp.decode_json("\"#{year}-02-10T00:00:00.000+00:00\""); print Time.at(t.seconds).to_s + "#{' # wrong' if Time.at(t.seconds).day != 10 }\n"; }
1900-02-10 00:00:00 +0000
1901-02-10 00:00:00 +0000
1902-02-10 00:00:00 +0000
1903-02-10 00:00:00 +0000
1904-02-10 00:00:00 +0000
1905-02-10 00:00:00 +0000
1906-02-10 00:00:00 +0000
1907-02-10 00:00:00 +0000
1908-02-10 00:00:00 +0000
1909-02-10 00:00:00 +0000
1910-02-10 00:00:00 +0000
1911-02-10 00:00:00 +0000
1912-02-10 00:00:00 +0000
1913-02-10 00:00:00 +0000
1914-02-10 00:00:00 +0000
1915-02-10 00:00:00 +0000
1916-02-10 00:00:00 +0000
1917-02-10 00:00:00 +0000
1918-02-10 00:00:00 +0000
1919-02-10 00:00:00 +0000
1920-02-10 00:00:00 +0000
1921-02-10 00:00:00 +0000
1922-02-10 00:00:00 +0000
1923-02-10 00:00:00 +0000
1924-02-10 00:00:00 +0000
1925-02-10 00:00:00 +0000
1926-02-10 00:00:00 +0000
1927-02-10 00:00:00 +0000
1928-02-10 00:00:00 +0000
1929-02-10 00:00:00 +0000
1930-02-10 00:00:00 +0000
1931-02-10 00:00:00 +0000
1932-02-10 00:00:00 +0000
1933-02-10 00:00:00 +0000
1934-02-10 00:00:00 +0000
1935-02-10 00:00:00 +0000
1936-02-10 00:00:00 +0000
1937-02-10 00:00:00 +0000
1938-02-10 00:00:00 +0000
1939-02-10 00:00:00 +0000
1940-02-10 00:00:00 +0000
1941-02-10 00:00:00 +0000
1942-02-10 00:00:00 +0000
1943-02-10 00:00:00 +0000
1944-02-10 00:00:00 +0000
1945-02-10 00:00:00 +0000
1946-02-10 00:00:00 +0000
1947-02-10 00:00:00 +0000
1948-02-10 00:00:00 +0000
1949-02-10 00:00:00 +0000
1950-02-10 00:00:00 +0000
1951-02-10 00:00:00 +0000
1952-02-10 00:00:00 +0000
1953-02-10 00:00:00 +0000
1954-02-10 00:00:00 +0000
1955-02-10 00:00:00 +0000
1956-02-10 00:00:00 +0000
1957-02-10 00:00:00 +0000
1958-02-10 00:00:00 +0000
1959-02-10 00:00:00 +0000
1960-02-10 00:00:00 +0000
1961-02-10 00:00:00 +0000
1962-02-10 00:00:00 +0000
1963-02-10 00:00:00 +0000
1964-02-10 00:00:00 +0000
1965-02-10 00:00:00 +0000
1966-02-10 00:00:00 +0000
1967-02-10 00:00:00 +0000
1968-02-10 00:00:00 +0000
1969-02-10 00:00:00 +0000
1970-02-10 00:00:00 +0000
1971-02-10 00:00:00 +0000
1972-02-10 00:00:00 +0000
1973-02-10 00:00:00 +0000
1974-02-10 00:00:00 +0000
1975-02-10 00:00:00 +0000
1976-02-10 00:00:00 +0000
1977-02-10 00:00:00 +0000
1978-02-10 00:00:00 +0000
1979-02-10 00:00:00 +0000
1980-02-10 00:00:00 +0000
1981-02-10 00:00:00 +0000
1982-02-10 00:00:00 +0000
1983-02-10 00:00:00 +0000
1984-02-10 00:00:00 +0000
1985-02-10 00:00:00 +0000
1986-02-10 00:00:00 +0000
1987-02-10 00:00:00 +0000
1988-02-10 00:00:00 +0000
1989-02-10 00:00:00 +0000
1990-02-10 00:00:00 +0000
1991-02-10 00:00:00 +0000
1992-02-10 00:00:00 +0000
1993-02-10 00:00:00 +0000
1994-02-10 00:00:00 +0000
1995-02-10 00:00:00 +0000
1996-02-10 00:00:00 +0000
1997-02-10 00:00:00 +0000
1998-02-10 00:00:00 +0000
1999-02-10 00:00:00 +0000
2000-02-10 00:00:00 +0000
2001-02-10 00:00:00 +0000
2002-02-10 00:00:00 +0000
2003-02-10 00:00:00 +0000
2004-02-10 00:00:00 +0000
2005-02-10 00:00:00 +0000
2006-02-10 00:00:00 +0000
2007-02-10 00:00:00 +0000
2008-02-10 00:00:00 +0000
2009-02-10 00:00:00 +0000
2010-02-10 00:00:00 +0000 So, this PR may not be necessary now 🙈 |
Still thanks for your help :) |
REF
Google::Protobuf::Timestamp.decode_json sometimes return incorrect timestamp values in Ruby #6616
WHY
In current implementation of protobuf/ruby, the result of counting leap days was wrong.
This caused the wrong result of
Google::Protobuf::Timestamp.decode_json
.Here are some other examples.
WHAT
I fixed the logic to count leap days.