날짜 계산

dcmru의 이미지

기본적인 식 힌트를 구합니다. ^^;

일단 1970년 1월 1일부터 어느 날짜까지의 날짜수는 구했습니다.

여기서 구한 날짜수를 다시 년월일로 표시할려고 하는데요.

윤년도 껴 있고 해서 다시 표시할려는데 생각이 언뜻 안나네요.

물론 날짜수를 계산할 때는 윤년을 포함하여 계산 하였습니다.

예로 2006-12-31일일까지의 날짜수는 13513입니다.

이 것을 다시 날짜로 표시할려면 어떻게 구해야할까요?

너무 기초적이다 생각마시구 도움 바랍니다

그리고 os에 포함된 함수로 구한 것이 아닙니다.

2030년까지의 제한이 있어서 식을 짜서 구한 것입니다......

1970년부터 올해까지는 9번의 윤년이 있었습니다.

ktd2004의 이미지

다음과 같은 방식은 어떨까요?

time_t tt;
struct tm ttm;
tt = 13513*60*60*24;
localtime_r( &tt, &ttm);
dcmru의 이미지

현재 컴파일러에 있는 함수로는 2030년가지의 제한이 있어서,

더큰 년도가 필요하여 식을 만들어서 계산을 해야합니다 ㅠㅠ

노력만이 살길이다.

노력만이 살길이다.

dcmru의 이미지

1970년부터 구한 날짜수를 1년씩 빼서 구했습니다. 윤년인 해는 366일을 빼고 평년은 365를 뺐습니다.

무식한 방법 같네요 ㅡㅡㅋ

더 간단한 방법이 없을가요?

노력만이 살길이다.

노력만이 살길이다.

ktd2004의 이미지

glibc의 localtime 소스를 분석해보는 건 어떨까요?
64bits 아키텍처의 glibc 소스는 아마 2038 문제가 없는 것으로 알고 있는데요..
64bits 아키텍처용의 glibc의 소스를 분석하고 구현한다면 되지 않을까 싶습니다.

성능이 중요하지 않다면, 직접 구현하신 코드가 정상적으로 동작한다면,
glibc 소스를 분석하는 것보다 그냥 사용하시는 것도 좋을 듯 싶습니다.

dcmru의 이미지

노력만이 살길이다.

노력만이 살길이다.

chadr의 이미지

무식하게 1년 1월 1일 부터 계산 하는 방법도 있습니다..

#include <stdio.h>
#include <conio.h>
//#include <stdlib.h>
 
int computedays(long, int);//1년 1월 1일부터 입력한 날까지 날짜수를 계산하고 매달 첫번째 날의
//위치를 구하는 함수
int printcalendertoscreen(long, int, int, int);//계산한 결과를 가지고 달력을 화면에 표시하는 함수
int printcalendertofile(long, int, int, int);//계산한 결과를 가지고 달력을 파일로 출력하는 함수
void errormsg(int);//에러메시지 출력 함수
long strTOnum(char *);//문자열을 숫자로 바꾸는 함수
int findEOS(char *);//문자열의 끝을 찾는 함수
//전역 변수 선언
int byyear=0, printok;
char strmonth[2], stryear[10], mode;
 
int main()
{
	int month, ok=0,  geti=0,  i;
	long year;
	char c, tmp;
 
	while(!ok)
	{
		printf("\n메 뉴\n\n");
		printf("1. 화면으로 표시\n");
		printf("2. 파일로 저장\n");
		printf("3. 종료\n");
		printf("\n원하는 모드를 고르세요.. : ");
 
		printok=0;
 
		mode=getche();
		putchar('\n');
 
		if(mode>='1' && mode<='3')
			mode-=48;
 
		else if(mode=='\n')
				mode=1;
 
		if(mode<1 || mode>3)
		{
			errormsg(1);
			fflush(stdin);
			ok=0;
			continue;
		}
 
		if(mode==3)
			break;
 
		fflush(stdin);
 
	do
		{
			printf("\n년단위 출력을 하시겠습니까? y or n : ");
			c=getche();
 
			if(c=='n' || c=='N' || c=='\r')
			{
				byyear=0;
				fflush(stdin);
				break;
			}
 
			else if(c=='y' || c=='Y')
			{
				byyear=1;
				fflush(stdin);
				break;
			}
			else
			{
				errormsg(1);
				fflush(stdin);
				continue;
			}
 
		}while(!(c=='y' || c=='Y' || c=='n' || c=='N' || c=='\r'));
 
		printf("\n년도를 입력하세요 : ");
 
		while((tmp=getchar())!='\n')//입력한 숫자를 하나씩 엔터가 읽힐때까지 읽음
		{
			stryear[geti]=tmp;//읽은 문자를 배열에 차곡차곡 저장함
			geti++;
		}
		stryear[geti]='\0';//입력받은 숫자를 스트링으로 만듦
		geti=0;// 스트링 카운터를 다시 0으로 세팅
 
		if((year=strTOnum(stryear))==0)
		{
			fflush(stdin);
			ok=0;
			continue;
		}
 
		if(year<1 || year>11767033)
		{
			errormsg(2);
			fflush(stdin);
			ok=0;
			continue;
		}
 
		if(byyear)
		{
			for(i=1; i<=12; i++)
			{
				computedays(year, i);
			}
			continue;
		}
 
		printf("달을 입력하세요 : ");
 
		while((tmp=getchar())!='\n')//입력한 숫자를 하나씩 엔터가 읽힐때까지 읽음
		{
			strmonth[geti]=tmp;//읽은 문자를 배열에 차곡차곡 저장함
			geti++;
		}
		strmonth[geti]='\0';//입력받은 숫자를 스트링으로 만듦
		geti=0;// 스트링 카운터를 다시 0으로 세팅
 
		if((month=(int)strTOnum(strmonth))==0)
		{
			fflush(stdin);
			ok=0;
			continue;
		}
 
		if(month<1 || month >12)
		{
			errormsg(2);
			fflush(stdin);
			ok=0;
			continue;
		}
 
		computedays(year, month);
 
		fflush(stdin);
 
	}
return 1;
}
 
int computedays(long year, int month)
{
	int months[12]={31,28,31,30,31,30,31,31,30,31,30,31};
	int i, day, yearflag=0, flag=0;
	unsigned long int result=1;//1년 1월 1일은 월요일이므로 
 
	for(i=1; i<year; i++)//입력한 년도 전년까지의 날 수를 구함
	{
		if((i % 4 == 0 && i % 100 != 0) || i % 400 == 0)//윤년일 경우
			yearflag++;
 
		result+=365;
	}
	result+=yearflag;
 
	for(i=1; i<month; i++)//입력한 년도 1월 부터 입력한 달까지의 날 수를 구함
	{
		switch(i)
		{
 
		case 2://2월달일 경우 
			result+=28;//28을 더함
			break;
		case 1://홀수 월일 경우
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			result+=31;//31을 더함
			break;
		case 4://짝수 월일 경우
		case 6:
		case 9:
		case 11:
			result+=30;//30을 더함
			break;
 
		}
	}
 
 
	if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)//윤년일 경우
		flag=1;//플래그에 1대입
 
	result+=1;//일을 더함
 
	while(1)//달력의 맨 첫줄에서 앞의 빈칸을 출력하기 위해서 계산
	{
		result%=7;
 
		if(result>=1 && result<=6)
		{
/*앞 빈칸의 갯수*/day=result-1;
			break;
		}
		else
		{
//0으로 나누어 떨어지는	
//날짜를 가진 달을 위해서 
/*따로 처리*/		day=6;
			break;
		}
	}
 
	months[1]+=flag;//2월달의 경우에 윤년일 경우 플래그를 더함
 
	if(mode==1)
		printcalendertoscreen(year, month, day, months[month-1]);
	else
		printcalendertofile(year, month, day, months[month-1]);
 
	return 1;
}
 
int printcalendertoscreen(long year, int month, int day, int months)
{
	int i/*달력의 칸수를 기억*/, space/*빈칸의 갯수*/, j/*실제 날을 기억*/;
 
	printf("\n%ld년도\n%13d월\n", year, month);//헤더 출력
	printf("일  월  화  수  목  금  토\n");
 
	space=day*4;//실제 빈칸의 갯수를 계산
 
	for(i=1; i<=space; i++)//빈칸 출력
		putchar(' ');
 
	for(i=1, j=1; i<=7-day; i++,j++)//달력의 맨처음 부분 출력
		printf("%2d  ", j);
 
	putchar('\n');
 
	for(i=1; j<=months; i++, j++)//달력의 나머지 부분 출력
	{
		 printf("%2d  ", j);
 
		 if(!(i%7))
			putchar('\n');
	}
	putchar('\n');
return 1;
}
 
int printcalendertofile(long year, int month, int day, int months)
{
	int i, strlen=-1/*달력의 칸수를 기억*/, space/*빈칸의 갯수*/, j/*실제 날을 기억*/;
	char filename[]={"00000000년 00월 달력.txt"}, *filenamep;
	char filenamebyyear[]={"00000000년 달력.txt"};
	char newline='\n', spacechar=' ';
	FILE *fp;
 
	if(byyear)
	{
		filenamep=filenamebyyear;
 
		strlen+=findEOS(stryear);
 
		for(i=7; strlen>=0; i--, strlen--)
			filenamep[i]=stryear[strlen];
 
		if((fp=fopen(filenamep, "a"))==NULL)
		{
			errormsg(3);
			return 0;
		}
	}
 
	else
	{
		filenamep=filename;
 
		strlen+=findEOS(stryear);
 
		for(i=7; strlen>=0; i--, strlen--)
			filenamep[i]=stryear[strlen];
 
		strlen+=findEOS(strmonth);
 
		for(i=12; strlen>=0; i--, strlen--)
			filenamep[i]=strmonth[strlen];
 
		if((fp=fopen(filenamep, "w"))==NULL)
		{
			errormsg(3);
			return 0;
		}
	}
 
	if(fprintf(fp, "\n%ld년도\n%13d월\n", year, month)==EOF)//헤더 출력
	{
		errormsg(4);
		return 0;
	}
 
	if(fprintf(fp, "일  월  화  수  목  금  토\n")==EOF)
	{
		errormsg(4);
		return 0;
	}
 
	space=day*4;//실제 빈칸의 갯수를 계산
 
	for(i=1; i<=space; i++)//빈칸 출력
		if(fputc((int)spacechar, fp)==EOF)
		{
			errormsg(4);
			return 0;
		}
 
	for(i=1, j=1; i<=7-day; i++,j++)//달력의 맨처음 부분 출력
		if(fprintf(fp, "%2d  ", j)==EOF)
		{
			errormsg(4);
			return 0;
		}
 
	if(fputc((int)newline, fp)==EOF)
	{
		errormsg(4);
		return 0;
	}
 
	for(i=1; j<=months; i++, j++)//달력의 나머지 부분 출력
	{
		 if(fprintf(fp, "%2d  ", j)==EOF)
		 {
			 errormsg(4);
			 return 0;
		 }
 
		 if(!(i%7))
			if(fputc((int)newline, fp)==EOF)
			{
				errormsg(4);
				return 0;
			}
	}
 
	if(fputc((int)newline, fp)==EOF)
	{
		errormsg(4);
		return 0;
	}
 
	fclose(fp);
 
	if(printok);
 
	else
	{
		printf("본 프로그램을 실행하신 위치에\n%s 이라는 파일명으로 저장을 완료했습니다.\n", filenamep);
		printok=1;
	}
return 1;
}
 
long strTOnum(char *numstring) 
{ 
        int i, j, length; 
        long result=0; 
 
        length=findEOS(numstring); //스트링의 길이를 구해서
        j=length; //j변수에 저장하고 length변수에 저장하여
		//스트링의 길이(즉, 자릿수)만큼 반복하여 원래 숫자를 구함
 
        for (i=0;i<length;i++,j--) 
        { 
 
                switch(numstring[i]) 
 
                { 
 
                case '-':break; //-부호가 있을경우 스위치문을 중지하고 숫자부터 읽음
 
				//j변수를 하나씩 감해가면서 자릿수를 구하고 입력받은 문자로
				//해당 자리의 원래 숫자를 구함
				case '1': 
 
				case '2':
 
				case '3':
 
				case '4':
 
				case '5':
 
                case '6':
 
                case '7':
 
                case '8':
 
                case '9':
 
				case '0':
					result=result*10+numstring[i]-'0';
					break; 
 
				default :
					errormsg(5);					
					fflush(stdin);
					return 0;//숫자외의 문자를 입력했을 경우 0을 리턴하여 에러메시지를 출력
							 //하게 함
 
				}
 
        } 
        if(numstring[0]=='-')//-부호가 있을경우 결과값에 -를 곱해줌 
                result=-result; 
 
		return result;//결과값을 리턴
}
 
int findEOS(char *svalue) //스트링의 길이를 구함.. \0을 미포함
{ 
        for(int i=0; ; i++) 
                if(!svalue[i]) 
                        return i; 
}
 
void errormsg(int errorcode)
{
	switch(errorcode)
	{
	case 1:
		printf("\n잘못 입력하셨습니다.\n");
		break;
 
	case 2:
		printf("\n허용범위를 넘는 숫자를 입력하셨습니다.\n다시 입력하세요.\n\n");
		break;
 
	case 3:
		printf("\n파일을 만들 수 없습니다.\n");
		break;
 
	case 4:
		printf("\n파일에 쓸 수 없습니다.\n");
		break;
 
	case 5:
		printf("\n숫자를 입력하세요.. ㅡㅡ+ 시킨대로 하길..\n\n");
		break;
 
 
	}
}

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.