[Include] TimestampToDate.inc - Convert a timestamp to a date!
#1

TimestampToDate & DateToTimestamp

Hello,

Unix Timestamps for beginners
For those who are not familliar with Unix Timestamps, take a look at Wikipedia (press the link).

Introduction
Today, I'll present one of my new works: TimestampToDate. This library is able to convert your specified timestamp to a date.

- Timezone supported.
- Leap years supported.
- Easy to use


The syntaxes are as followed:

Explanation
pawn Код:
stock TimestampToDate(Timestamp, &year, &month, &day, &hour, &minute, &second, HourGMT, MinuteGMT = 0)
Notice the last two parameters. GMT is the timezone in which we live. It's taken as the standard timezone. You should only fill in MinuteGMT if you live in a timezone which has for example: 6.5.

The year, month, day, hour, minute and second parameters should be filled in like you do in getdate and gettime.

Since v2.0, this library contains a new stock: DateToTimestamp. I will explain this as well.
pawn Код:
stock DateToTimestamp(str[11])
You could compare this with strtotime/mktime in PHP. The only parameter is a string, which is the date that should be converted to a timestamp. It should be in the following format: 06.04.2013. The "." here is the splitter. It can be changed to any character you wish (as long as you don't use numeric characters, it will probably work). It should be changed by redefining "#SPLITTER" after including this library.

Download
v2.0 --> http://pastebin.com/7LQB5Ki1
Example --> http://pastebin.com/HP9F63a2


- Open the link and press RAW.
- Copy all text and save it right here: "server_dir/pawno/includes" under filename: TimestampToDate.inc.
- Add "#include <TimestampToDate>" in the script you'd like to use it (gamemode?).


Do not redistribute this without my permission. Link people to this topic instead of direct download. It will be appreciated!
Reply
#2

You can choose the GMT in which you live. Leap years are hard to make indeed, but debugging showed it works (for me) and it was hard to think about. Just the tests I tried showed it works, but of course it might be a bit buggy.

Код:
[13:41:00] tmp = 2, timestamp: 1307101260
[13:41:00] tmp = 1, timestamp: 1275565260
[13:41:00] LEAP YEAR - timestamp: 1243942860
[13:41:00] tmp = 4, timestamp: 1212406860
[13:41:00] tmp = 3, timestamp: 1180870860
[13:41:00] tmp = 2, timestamp: 1149334860
[13:41:00] tmp = 1, timestamp: 1117798860
[13:41:00] LEAP YEAR - timestamp: 1086176460
[13:41:00] tmp = 4, timestamp: 1054640460
[13:41:00] tmp = 3, timestamp: 1023104460
[13:41:00] tmp = 2, timestamp: 991568460
[13:41:00] tmp = 1, timestamp: 960032460
[13:41:00] LEAP YEAR - timestamp: 928410060
[13:41:00] tmp = 4, timestamp: 896874060
[13:41:00] tmp = 3, timestamp: 865338060
[13:41:00] tmp = 2, timestamp: 833802060
[13:41:00] tmp = 1, timestamp: 802266060
[13:41:00] LEAP YEAR - timestamp: 770643660
[13:41:00] tmp = 4, timestamp: 739107660
[13:41:00] tmp = 3, timestamp: 707571660
[13:41:00] tmp = 2, timestamp: 676035660
[13:41:00] tmp = 1, timestamp: 644499660
[13:41:00] LEAP YEAR - timestamp: 612877260
[13:41:00] tmp = 4, timestamp: 581341260
[13:41:00] tmp = 3, timestamp: 549805260
[13:41:00] tmp = 2, timestamp: 518269260
[13:41:00] tmp = 1, timestamp: 486733260
[13:41:00] LEAP YEAR - timestamp: 455110860
[13:41:00] tmp = 4, timestamp: 423574860
[13:41:00] tmp = 3, timestamp: 392038860
[13:41:00] tmp = 2, timestamp: 360502860
[13:41:00] tmp = 1, timestamp: 328966860
[13:41:00] LEAP YEAR - timestamp: 297344460
[13:41:00] tmp = 4, timestamp: 265808460
[13:41:00] tmp = 3, timestamp: 234272460
[13:41:00] tmp = 2, timestamp: 202736460
[13:41:00] tmp = 1, timestamp: 171200460
[13:41:00] LEAP YEAR - timestamp: 139578060
[13:41:00] tmp = 4, timestamp: 108042060
[13:41:00] tmp = 3, timestamp: 76506060
[13:41:00] tmp = 2, timestamp: 44970060
[13:41:00] tmp = 1, timestamp: 13434060
But thanks for looking. I can always do something with what you say ^^
Reply
#3

Update (v1.1)
Removed the while loop and replaced it with an never-ending for loop. It will break after a few times though. All the years (so also the leap years) are in the loop now.
Reply
#4

Quote:
Originally Posted by ******
Посмотреть сообщение
Yeah, I realised that 2000 WAS a leap year because it was a multiple of 400, when other multiples of 100 are not, and any of the years where that is a factor are beyond the range of 32 bit integers. You realise you can do this with vastly less loops right? You don't need to loop over every year, just work out the number of leap years in between and do a huge multiply.
What ever happened to you giving constructive criticism?
Reply
#5

Are you F***ing kidding me -.-, I couldn't find anything like this a month ago therefore I made it now I goto this section and the first thing I see is this flashing in front my eyes.

OT: Great Release its better than stamping values so should be good for a lot of people, mainly idots who are crap at maths.
Reply
#6

It's good to have some critism so I can improve it.

Quote:
Originally Posted by IceCube!
Посмотреть сообщение
OT: Great Release its better than stamping values so should be good for a lot of people, mainly idots who are crap at maths.
@ IceCube: Glad you like it! In fact, timestamps are really useful! Have you ever thought about creating time-mutes, timebans, timefreeze, .... ? Get the timestamp, count the seconds on there and run a 10-second timer or so. Timestamps is something which too many people have not discovered.

Quote:
Originally Posted by ******
Посмотреть сообщение
It could maybe have been slightly more constructive by giving a full formula, but it was just a quick reply. I had previously thought that the leap year calculation was wrong, and while technically it is, that reply was mostly to state that I realised that the calculation is correct for any period of time that this code will be used in.
Unsure if you mean this - but I tried to run this code when I set my windows-time to 2099, and the server crashed (too big integer?)
Reply
#7

Amazing work with this one
Reply
#8

Quote:
Originally Posted by Niko_boy
Посмотреть сообщение
Amazing work with this one
Thanks, I am writing an example at this stage so you guys can see an example function.
Reply
#9

Quote:
Originally Posted by ******
Посмотреть сообщение
Sort of, yes. It will fail on years like 2101, but since their timestamps are outside the range of 32bit numbers, it doesn't matter.
We must be working with 1024 bit systems then.
Reply
#10

is there any way we can use 64, or even 128 bit integers in samp?
Reply
#11

Quote:
Originally Posted by legodude
Посмотреть сообщение
is there any way we can use 64, or even 128 bit integers in samp?
Probably not.
Reply
#12

so if im understanding correctly, it is possible, but hacky, so youd need some kind of native code implementation to do it?
Reply
#13

Quote:
Originally Posted by ******
Посмотреть сообщение
Yes, someone wrote a library for 64 bit integers, though you need to be careful as they're not brilliant if not done right. It may be better to write a plugin.
Why would you even consider using 64 bit ints? It's not like we will be playing sa-mp in even 30 years time, ever mind 100.
Reply
#14

Lol, I'd be attempting to make my own SA-MP in thirty years

OT

Should function well enough till SA-MP lives. Never-the-less, well done.
Reply
#15

Thank you!

Oh btw, leap seconds are not counted in timestamps.
Reply
#16

Hi Jochemd, I think it's great that you decided to make this useful include.

I had a quick look at your code and I think it doesn't support negative timestamp. I made something like this the other day in C as a part of my programming assignment and I wanted to port it to PAWN, but seeing as you are already working on it, I may as well share my C code here. It supports negative timestamps, but doesn't regard timezones, but it's easy to implement.

Код:
bool is_leap_year(int year)
{
	/*
		This function checks if given year is a leap year: 
		it must be divisible by 4 and not divisible by 100 unless it's also divisible by 400
		- according to wikipedia
	*/
	return ((year % 4) == 0 && (((year % 100) != 0) || ((year % 400) == 0)));
}

int get_num_days(int year)
{
	/*
		Simple function, just returns number of days in given year: either 365 or 366 (leap year)
	*/
	return (is_leap_year(year)?366:365);
}

void timestamp_to_date(int timestamp, int *y, int *m, int *d, int *h, int *min, int *s)
{
	/*
		This is a highly sophisticated function that I created. It turns timestamp into ymd and hms.
		
	*/
	int days = timestamp / (60*60*24), //converting timestamp to days by dividing it by number of seconds in a day
		month_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //defining number of days in a month
	/*
		Initialising starting date
	*/	

	if (timestamp >= 0)
	{
		/*
			Getting time of the day is very simple, So I do it first.
			Just take the ramainder from dividing by number of seconds in a day
		*/
		*s = timestamp % (60*60*24);

		*min = *s / 60;		//convert seconds to minutes...
		*s = *s % 60;		//...and keep the remainder

		*h = *min / 60;		//Same goes for hours...
		*min = *min % 60;	//...and minutes
	
		/*
			Now the ugly part: 'day' stores number of days since 1st January 1970.
			Somehow this has to be converted into a date.
			It's tricky, since some years have 366 days, some have 365.
		*/

		*d = 1;
		*m = 1;
		*y = 1970;

		int year_days;	//this variable stores number of days in current year, so I don't have to call the function twice in each iteration (efficiency)
		while (days > (year_days = get_num_days(*y)))
		{
			/*
				And loop through all years, substracting number of days passed each year...
				.. until number of days left is less than number of days in that year
			*/
			days -= year_days;
			 (*y)++;
		}

		/*
			Now tha I know what year it is, time to ensure that number of days in february is correct for the current year:
		*/
		if (is_leap_year(*y)) month_days[1] = 29;

		while (days > month_days[(*m)-1])
		{
			/*
				Looking for the month the same way I was looking for year
			*/
			days -=  month_days[(*m)-1];
			(*m)++;
		}
		// Remaining number of days is obviously the day of the month.
		*d += days;
	}
	else //same thing but in reverse
	{
		int year_days;
		days = -days;

		*s = -((timestamp) % (60*60*24))-1;

		*min = *s / 60;
		*s = *s % 60;

		*h = *min / 60;
		*min = *min % 60;
		
		*s = 59 - (*s);
		*min = 59-(*min);
		*h = 23-(*h);
		
		*d = 31;
		*m = 12;
		*y = 1969;

		while (days > (year_days = get_num_days(*y)))
		{
			days -= year_days;
			(*y)--;
		}

		if (is_leap_year(*y)) month_days[1] = 29;

		while (days > month_days[(*m)-1])
		{
			days -=  month_days[(*m)-1];
			(*m)--;
		}
		*d =  month_days[(*m)-1] - days;
	}
}
Reply
#17

Negative timestamps? It indeed doesn't.
Reply
#18

would not this be easier using php code via http function ?
Reply
#19

Quote:
Originally Posted by Hanger
Посмотреть сообщение
would not this be easier using php code via http function ?
Maybe. Why would you use PHP code - this works and barely takes 1 milisecond.
Reply
#20

can u reupload the Example ?
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)