www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.datetime

reply drug <drug2004 bk.ru> writes:
unittest
{
	import std.datetime : SysTime, UTC;

	{
		auto st = SysTime();
		st.timezone(UTC());

		long date  = st.fromISOExtString("2017-02-10T00:00:00Z").stdTime,
			time_of_day = st.fromISOExtString("0000-01-01T23:59:50Z").stdTime,
			timestamp   = st.fromISOExtString("0000-01-01T23:59:55Z").stdTime;

		import std.stdio;
		st.stdTime(date);
		writeln(st);
		st.stdTime(timestamp);
		writeln(st);
		st.stdTime(date+timestamp);
		writeln(st);
	}
}

prints
```
2017-Feb-10 00:00:00Z
0000-Jan-01 23:59:55Z
2016-Feb-10 23:59:55Z
```
I expect
```
2017-Feb-10 00:00:00Z
0000-Jan-01 23:59:55Z
2017-Feb-10 23:59:55Z
```

Why does it decrement years? What do I do wrong?
Feb 10 2017
parent reply drug <drug2004 bk.ru> writes:
10.02.2017 14:15, drug пишет:
 unittest
 {
     import std.datetime : SysTime, UTC;

     {
         auto st = SysTime();
         st.timezone(UTC());

         long date  = st.fromISOExtString("2017-02-10T00:00:00Z").stdTime,
             time_of_day =
 st.fromISOExtString("0000-01-01T23:59:50Z").stdTime,
             timestamp   =
 st.fromISOExtString("0000-01-01T23:59:55Z").stdTime;

         import std.stdio;
         st.stdTime(date);
         writeln(st);
         st.stdTime(timestamp);
         writeln(st);
         st.stdTime(date+timestamp);
         writeln(st);
     }
 }

 prints
 ```
 2017-Feb-10 00:00:00Z
 0000-Jan-01 23:59:55Z
 2016-Feb-10 23:59:55Z
 ```
 I expect
 ```
 2017-Feb-10 00:00:00Z
 0000-Jan-01 23:59:55Z
 2017-Feb-10 23:59:55Z
 ```

 Why does it decrement years? What do I do wrong?
I found error - years should start from 1, not 0. But if months or days start from 0 std.datetime throws exception and don't for years - it isn't clear that zero year is negative one (in that mean that stdTime for '0000' years will be negative.
Feb 10 2017
parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Friday, February 10, 2017 14:35:28 drug via Digitalmars-d-learn wrote:
 I found error - years should start from 1, not 0.
 But if months or days start from 0 std.datetime throws exception and
 don't for years - it isn't clear that zero year is negative one (in that
 mean that stdTime for '0000' years will be negative.
As the documentation states in multiple places, std.datetime follows ISO 8601, which uses the Proleptic Gregorian Calendar, and that specifies that the year 0 is equivalent to what you would normall consider to be 1 B.C. And that's part of the spec for the ISO extended format that fromISOExtString uses. Now, while it is mentioned in multiple places that std.datetime follows ISO 8601 and that it follows the Proleptic Gregorian Calender (even providing a link to wikipedia), it does look like it fails to specifically mention that on the primary ddoc comment of SysTime. So, that should be improved. However, the documentation for SysTime.year does state that positive years are A.D., whereas non-positive are B.C. So, the information is there, even without having to look up the Proleptic Gregorian Calender or ISO 8601. What would have made it clearer for you? - Jonathan M Davis
Feb 10 2017
parent reply drug <drug2004 bk.ru> writes:
10.02.2017 18:02, Jonathan M Davis via Digitalmars-d-learn пишет:
 On Friday, February 10, 2017 14:35:28 drug via Digitalmars-d-learn wrote:
 I found error - years should start from 1, not 0.
 But if months or days start from 0 std.datetime throws exception and
 don't for years - it isn't clear that zero year is negative one (in that
 mean that stdTime for '0000' years will be negative.
As the documentation states in multiple places, std.datetime follows ISO 8601, which uses the Proleptic Gregorian Calendar, and that specifies that the year 0 is equivalent to what you would normall consider to be 1 B.C. And that's part of the spec for the ISO extended format that fromISOExtString uses. Now, while it is mentioned in multiple places that std.datetime follows ISO 8601 and that it follows the Proleptic Gregorian Calender (even providing a link to wikipedia), it does look like it fails to specifically mention that on the primary ddoc comment of SysTime. So, that should be improved. However, the documentation for SysTime.year does state that positive years are A.D., whereas non-positive are B.C. So, the information is there, even without having to look up the Proleptic Gregorian Calender or ISO 8601. What would have made it clearer for you? - Jonathan M Davis
Is zero positive or negative? May be add statement that zero year is 1 B.C.? Thank you for your good job!
Feb 10 2017
parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Friday, February 10, 2017 19:06:53 drug via Digitalmars-d-learn wrote:
 10.02.2017 18:02, Jonathan M Davis via Digitalmars-d-learn пишет:
 On Friday, February 10, 2017 14:35:28 drug via Digitalmars-d-learn 
wrote:
 I found error - years should start from 1, not 0.
 But if months or days start from 0 std.datetime throws exception and
 don't for years - it isn't clear that zero year is negative one (in
 that
 mean that stdTime for '0000' years will be negative.
As the documentation states in multiple places, std.datetime follows ISO 8601, which uses the Proleptic Gregorian Calendar, and that specifies that the year 0 is equivalent to what you would normall consider to be 1 B.C. And that's part of the spec for the ISO extended format that fromISOExtString uses. Now, while it is mentioned in multiple places that std.datetime follows ISO 8601 and that it follows the Proleptic Gregorian Calender (even providing a link to wikipedia), it does look like it fails to specifically mention that on the primary ddoc comment of SysTime. So, that should be improved. However, the documentation for SysTime.year does state that positive years are A.D., whereas non-positive are B.C. So, the information is there, even without having to look up the Proleptic Gregorian Calender or ISO 8601. What would have made it clearer for you? - Jonathan M Davis
Is zero positive or negative? May be add statement that zero year is 1 B.C.? Thank you for your good job!
Neither. It's zero. That's why the documentation says that B.C. is non-positive - non-positive encompasses all of the negative numbers plus zero. And on yearBC, it does say that 0 is treated as 1 B.C. year doesn't mention that, but it's right above yearBC in the docs. It should probably link to yearBC though to make that clearer. B.C. does get kind of wonky though, since mathematically, it pretty much _has_ to be the case that 1 B.C. is 0 unless you just skip 0 (since otherwise all of the A.D. years get shifted by one, and then the years that most everyone uses would be shifted by one - e.g. 2017 would become 2016, which obviously doesn't work). And skipping 0 - as is done when normally talking about A.D. and B.C. - is just plain messy mathematically, just like trying to deal with the switch between the Julian and Gregorian calendars is a mess (even without getting into the issues related to different regions switching calendars at different times) - which is why ISO 8601 uses the Proleptic Gregorian Calendar, making it Gregorian the whole way. It's very mathematically neat, but it then runs afoul of how folks normally think of dates in the B.C. range. So, ultimately, it seems to be the best of a variety of bad answers to the problem. Gregorian Calender but didn't implement B.C. But then that gets pretty weird when you have 0 hnsecs be the default value, since once you have time zones west of UTC, you suddenly end up with them being in B.C., and if you don't have B.C... I ported std.datetime to C++ once where I was working, and I tried to strip out stuff like B.C. thinking that it would make the code simpler, and it actually made it worse. So, yeah, it's just messy all around. Fortunately, most code doesn't actually care about dates that far back, and for the code that does, there's yearBC for anyone who wants a date that looks more familiar. - Jonathan M Davis
Feb 10 2017
parent drug <drug2004 bk.ru> writes:
10.02.2017 19:31, Jonathan M Davis via Digitalmars-d-learn пишет:
 On Friday, February 10, 2017 19:06:53 drug via Digitalmars-d-learn wrote:
 10.02.2017 18:02, Jonathan M Davis via Digitalmars-d-learn пишет:
 On Friday, February 10, 2017 14:35:28 drug via Digitalmars-d-learn
wrote:
 I found error - years should start from 1, not 0.
 But if months or days start from 0 std.datetime throws exception and
 don't for years - it isn't clear that zero year is negative one (in
 that
 mean that stdTime for '0000' years will be negative.
As the documentation states in multiple places, std.datetime follows ISO 8601, which uses the Proleptic Gregorian Calendar, and that specifies that the year 0 is equivalent to what you would normall consider to be 1 B.C. And that's part of the spec for the ISO extended format that fromISOExtString uses. Now, while it is mentioned in multiple places that std.datetime follows ISO 8601 and that it follows the Proleptic Gregorian Calender (even providing a link to wikipedia), it does look like it fails to specifically mention that on the primary ddoc comment of SysTime. So, that should be improved. However, the documentation for SysTime.year does state that positive years are A.D., whereas non-positive are B.C. So, the information is there, even without having to look up the Proleptic Gregorian Calender or ISO 8601. What would have made it clearer for you? - Jonathan M Davis
Is zero positive or negative? May be add statement that zero year is 1 B.C.? Thank you for your good job!
Neither. It's zero. That's why the documentation says that B.C. is non-positive - non-positive encompasses all of the negative numbers plus
yes, it's my fault
 zero. And on yearBC, it does say that 0 is treated as 1 B.C. year doesn't
 mention that, but it's right above yearBC in the docs. It should probably
 link to yearBC though to make that clearer.

 B.C. does get kind of wonky though, since mathematically, it pretty much
 _has_ to be the case that 1 B.C. is 0 unless you just skip 0 (since
 otherwise all of the A.D. years get shifted by one, and then the years that
 most everyone uses would be shifted by one - e.g. 2017 would become 2016,
 which obviously doesn't work). And skipping 0 - as is done when normally
 talking about A.D. and B.C. - is just plain messy mathematically, just like
 trying to deal with the switch between the Julian and Gregorian calendars is
 a mess (even without getting into the issues related to different regions
 switching calendars at different times) - which is why ISO 8601 uses the
 Proleptic Gregorian Calendar, making it Gregorian the whole way. It's very
 mathematically neat, but it then runs afoul of how folks normally think of
 dates in the B.C. range. So, ultimately, it seems to be the best of a
 variety of bad answers to the problem.


 Gregorian Calender but didn't implement B.C. But then that gets pretty weird
 when you have 0 hnsecs be the default value, since once you have time zones
 west of UTC, you suddenly end up with them being in B.C., and if you don't
 have B.C... I ported std.datetime to C++ once where I was working, and I
 tried to strip out stuff like B.C. thinking that it would make the code
 simpler, and it actually made it worse. So, yeah, it's just messy all
 around. Fortunately, most code doesn't actually care about dates that far
 back, and for the code that does, there's yearBC for anyone who wants a date
 that looks more familiar.

 - Jonathan M Davis
Thank you for your answer!
Feb 10 2017