TimeStamp
#1
Posté 14 juillet 2011 - 12:07
void TimeStamp(){
int iSecond = GetTimeSecond();
int iMinute = GetTimeMinute()*60;
int iHour = (GetTimeHour()*60)*60;
int iDay = ((GetCalendarDay()*24)*60)*60;
int iMonth = (((GetCalendarMonth()*28)*24)*60)*60;
int iYear = ((((GetCalendarYear()*336)*28)*24)*60)*60;
return iSecond+iMinute+iHour+iDay+iMonth+iYear;
}
first of all, it is right that the days in a month are 28?
Secondly, this function give me bad result due to INT limitation of nwn. Take 10 as the actual year and launch the function, the right result should be 8.128.512.000, nwn have an int limitation of 2.147.483.647 (taken from the lexicon)
Any hint or correction?
#2
Posté 14 juillet 2011 - 12:44
As for your script, I don't expect it's needed to go *336 * 28. It should probably be *336 or *28*12.
#3
Posté 14 juillet 2011 - 01:17
Thanks anyway with the multiplication error, misspelling when debugging the function.. (like the void declaration)
#4
Posté 14 juillet 2011 - 01:20
#5
Posté 14 juillet 2011 - 02:22
#6
Posté 14 juillet 2011 - 03:39
Failed.Bard wrote...
I hadn't realized it didn't overwrite strings. A quick look at my timestamp database put it at 2.1 megs for storing a 13 digit string. Is it just strings it does this with, or will it do it with floats as well?
It will do it with any Non-fixed length data type.
There are only two of them that can be stored in the DB. Strings and Objects.
All of the other ones just over write the 128 byte buffer in the original record.
If the data type is larger or even has a chance of being larger then 182 bytes, it stores a pointer to the data in the 128 byte buffer. When the data is overwritten with this system, it appends the new data to the end of the data file and writes a new pointer to it in the 128 byte data field. The old data is just left where ever it was at and ingnored.
#7
Posté 14 juillet 2011 - 04:07
Lightfoot8 wrote...
http://social.biowar...4495419#4495419
whoa, it's a long reading
But the thread is regarding the writing of the time in the db (i don't use the bio db) and i can't reproduce that for a time stamp function (newbie with the modulo operator here!)
I think i will use the time stamp as a string variable and i will create 3 function, encode (transform actual year, month etc in a string with some special character divider) , decode (that accept what type of return) and a compare one
Modifié par Epitaffio, 14 juillet 2011 - 04:10 .
#8
Posté 14 juillet 2011 - 04:30
multiplication uses a maximum range while shift is slighly faster, not any speed you will notice.
#9
Posté 14 juillet 2011 - 04:35
ie Min*60 is perfect but Min<<6 (same Min*64) will give the same result when doing compare results. you only waste some number ranges.
#10
Posté 14 juillet 2011 - 06:09
I also note that you are multiplying your minutes by 60 to get the number of hours. Nwn hours do not have 60 minutes in them. The number of minutes in a nwn hour is set in the module properties. Standard is 2. minutes and below are real time. hours and above are game time.
#11
Posté 17 juillet 2011 - 06:06
#12
Posté 17 juillet 2011 - 06:28
#13
Posté 17 juillet 2011 - 08:01
float iMinPerHour = HoursToSeconds(1)/60; //20
float iMinPerDay = 24 * iMinPerHour; //480
float iMinPerMonth = 28 * iMinPerDay; //13440
float iMinPerYear = 12* iMinPerMonth; //161280
float iMinute = IntToFloat(GetTimeMinute()); //0
float iHour = (GetTimeHour()+1) * iMinPerHour; //(23+1)*20 480
float iDay = GetCalendarDay() * iMinPerDay; //28*480 13440
float iMonth = GetCalendarMonth() * iMinPerMonth; //12*13440 161280
float iYear = GetCalendarYear() * iMinPerYear; //1305*161280 210470400
float iTimestamp = iMinute + iHour + iDay + iMonth + iYear; //210645600
Next of each row, there is an example of the max value (for the year i think we will have only 3 digit, but for testing i've just used the 4 one). I hope it's this what you asked me (i'm not english mother language, so sometimes i misunderstand
#14
Posté 17 juillet 2011 - 09:28
Epitaffio wrote...
This is my latest version of the function, with the float variables (no code tag = hate)
float iMinPerHour = HoursToSeconds(1)/60; //20
float iMinPerDay = 24 * iMinPerHour; //480
float iMinPerMonth = 28 * iMinPerDay; //13440
float iMinPerYear = 12* iMinPerMonth; //161280
Next of each row, there is an example of the max value (for the year i think we will have only 3 digit, but for testing i've just used the 4 one). I hope it's this what you asked me (i'm not english mother language, so sometimes i misunderstand)
changed this section just a tad. the -1 is to make te numbers 0 based. this makes it easier to exstract your original times back out.
float iMinute = IntToFloat(GetTimeMinute() -1 ); //0
float iHour = GetTimeHour() * iMinPerHour; //(24)*20 480
float iDay = (GetCalendarDay()-1 )* iMinPerDay; //28*480 13440
float iMonth = (GetCalendarMonth()-1 ) * iMinPerMonth; //12*13440 161280
float iYear = GetCalendarYear() * iMinPerYear; //1305*161280 210470400
Yes that is what I needed. So it looks like you are running a server with 20min/hour.
To answer your question: no this will not work. Here is the reasion why.
the single precison float(32 bit) format that nwn uses has only 6 1/2 digits of precision. this means that you can only rely on the value of the 6 most significent digits in the number. lets look at this in relation to your number.
If we have the date/ time
year 6
month 1
day 1
time 0:00
your time stamp would be
6 years *161280min/year
+ (1-1)months * 480min/month
+ (1-1)day * 13440min/day
+ 0hour * 20min/hour
+ 0min
= 967,680min
So for 6 years we have a time stamp of 967,680 minutes. This is no problem and within the limitations of the nwn float.
lets see what year 7 looks like
7 years *161280min/year = 1,128,960
now we have a problem, our number is 7 digits long. the last digit in the number only has a 50% chance of being accurate. This means that if you added a single minute to your time stamp. It might get add it might not. Or it could even add 2 minutes instead of the one your where trying to add.
once you go out to year 70 you would then have 8 digits in the number and adding minutes in blocks of less the 10 would most likely have no effect on your stamp at all. minutes in quanites of less then 100 would have inacurate results but would at least have a chance to effect the stamp.
So the short answer here is No. the float is a bad solution for this method,.
the int on the other hand will give you a number that can go all the way up to 2,147,483,648 with being accurate. that is 9.2 digits of accuracy.
with the method above you coud accuratly store 13,315 years into the int and less then 7 years into the float.
#15
Posté 17 juillet 2011 - 10:18
So, finally.. i can't use float for the accuracy... if i use int with seconds, i will reach the int limit.
The only solution i can see is to use int without seconds, it's right?
Just a last thing, you have corrected my script with the -1 to use a 0 based values, but in case of the first XXX, where XXX is one of the -1 value, i will have a 0 result. Why this will help me to extract the initial result? It's modulo related?
#16
Posté 17 juillet 2011 - 10:27
Funky
Modifié par FunkySwerve, 17 juillet 2011 - 10:29 .
#17
Posté 18 juillet 2011 - 12:29
UNIX Timestamp: seconds since Jan 1 1970 ex. Jan 1 1970 1:00am = 3600 or 60*60 (Min *Sec)
Mac Timestamp: seconds since Jan 1 1904 es Jan 1 1904 2.00am = 7200 or 120*60 ( (min*Sec)
both of thies are stright forward where the time stamp is an unsinged intenger of the number of seconds from the given date. .
here is the Mircrosoft time stamp.
Microsoft Timestamp: days since Dec 31 1899
note: mircrosoft does not use the number of seconde from the given date. Instead it it the number of days. inorder to get an acurate time they use a double pricesion float, where the mumber of days is represented by whole numbers and the time during the day is representsd the fraction of the number. so:
January 1, 1900 12:00Pm would have a time stamp of 0.5 or half after december 31 1989.
January 2, 1900 6:00Pm would have a time stamp of 1.75 or 1 and three quraters of a day after december 31 1989.
The time stamp you are devloping is doing basicly the same thing, you just have not added a way for a starting date that is higher then jan 1 year 0. but I have not really answered you question yet.
to simplify it a little lets just look at a stamp for nwn that would be the number of days and we will still use year 0 for simplisity. So we would have.
//multiplyers:
int nmlDay = 1; //there is 1 day per day.
int nmlMonth = 28; //There are 28 days per month.
int nmlyear =436 // there are 336 days per year.
// now lets create a time stamp with this without using the -1's that I included. lets take:
year 0.
month 12
day 28
Our time stamp is : 12 * 28 + 28 = 364
now lets try and get our number of years, months and days back out of the stamp.
lets see if we devide our number by the number of years we should get our year.
364 / 336 = 1 with a remainde of 28. so we have 1 year.
now if we take the remainder and devide it by the number of days per month we should get the month. with the remainder being the number of days.
28/28 = 1 remainder 0
so pulling our date back out of the stamp we get
year 1
month 1
day 0
Hmm it does really what we where looking for. The problem is that we are using a day of 1 to 28 in our equasions where 28 is also 1 month. and using 1-12 months where 12 months is also 1 year. So that is how they are returned to us. not to mention that our numbering system is somehow missing the fact that I can be one be 28 day away from my start date.
Again for simplicity lets look a a different date to find the problem. lets say:
year 0
month 1
day 1
hour 12:00pm // yea I know I gave it a time.
with the date given above what shoud our time stamp be if it is the number of days form year 0.
well it is still in the first day. If we had decimal places it would be 0.5, half a day. The fact is that on day 1 month 1 a day has not yet passed and a month surly has not yet passed. To simplify getting the same date out of a time stamp that we put into the time stamp we change the way the months and days are numbered from days: 1-28 to days 0 -27. or just day-1
and for months from 1- 12 to 0-11
notice that 1-12 and 0 -11 still has the same nunber of members in the set. { 1,2,3,4,5,6,7,8,9,10,11,12] and [0,1,2,3,4,5,6,7,8,9,10,11] both sets have 12 members. the 0-11 is the preferred usage because it is 0 based making it so the upper limit does not (11) does not get confused with a full year like the upper limit of the other set (12) would.
so lets look back at our orginal try that returned the wrong date when we tryed to convert it back from the stamp.
year 0.
month 12
day 28
if we are in month 12 , 12 months have not yet passed . 11 months have passed putting us in the 12 month.
on day 28 only 27 days have fully passed.
so we now have
(12-1) *28 + (28-1) = 335 days since year 0
ok let convert it nack to a year/ month/day
stamp / the number days in a year should give us the number of years with a remainder of days into the year.
335/ 336 = 0 remainder of 336.
ok so far so goor we get year 0.
now when we divide the 'days into the year' by the number of days in a month we should get the number of month that have passed. with a remander of days that have passed into the month.
335/28 = 11 with a remainder of 27
now that is not quite the number we started with. Just keep in mind what the 11 and 27 are. they are the munber months and days that have passed. if 11 months have already passed we are not in month 11, we are in month 12. So the month we are in will always be "the months that have passed +1" same thing with the days.
so we now have
(335/28) +1 = our month.
our day is the remainder (27 +1) = day 28.
now let me try and work in the modulo '%" operator.
the only thing the modulo does is return the remainder of the division.
so in our last division there where we had the nimber of days into the year. 335 of them
335 / 28 = 11
now if we need to find the remainder for our number of days wy can either muntiply 28 by 11 and then subtract it from our original 335
335 - (28*11) = 27
or we can just use the modulo to give us the remainder.
335 % 28 = 27
I hope that explains everything.
L8
#18
Posté 18 juillet 2011 - 10:15
#19
Posté 18 juillet 2011 - 11:41
int iMinPerHour = FloatToInt(HoursToSeconds(1)/60);
int iMinPerDay = 24*iMinPerHour;
int iMinPerMonth = 28*iMinPerDay;
int iMinPerYear = 12*iMinPerMonth;
int iMinute = GetTimeMinute();
int iHour = GetTimeHour() * iMinPerHour;
int iDay = (GetCalendarDay()-1) * iMinPerDay;
int iMonth = (GetCalendarMonth()-1) * iMinPerMonth;
int iYear = GetCalendarYear() * iMinPerYear;
int iTimestamp = iMinute + iHour + iDay + iMonth + iYear;
Here the decoding:
int iTestYear = iTimestamp/iMinPerYear;
iTimestamp = iTimestamp%iMinPerYear;
int iTestMonth = iTimestamp/iMinPerMonth +1;
iTimestamp = iTimestamp%iMinPerMonth;
int iTestDay = iTimestamp/iMinPerDay +1;
iTimestamp = iTimestamp%iMinPerDay;
int iTestOre = iTimestamp/iMinPerHour;
iTimestamp = iTimestamp%iMinPerHour;
int iTestMinuti = iTimestamp;
#20
Posté 18 juillet 2011 - 08:22
#21
Posté 06 mars 2012 - 12:38
http://pastebin.com/xnJMcHFR
I saw the comment above that game hours are not necessarily equalt to 60 game minutes. This is true. I create a constant in my modules that represents a conversion from game minutes to real minutes. So if a game hour is only 2 game minutes, the value of my constant is 30 (meaning 30 real minutes per game minute).





Retour en haut






