기록장

[C++] Date클래스: time(0)으로 현재 날짜 구하기 (구조체사용 안 함) 본문

코딩 공부/C++

[C++] Date클래스: time(0)으로 현재 날짜 구하기 (구조체사용 안 함)

민j 2023. 3. 23. 00:22

<C++로 시작하는 객체지향 프로그래밍> 403p 실습 9.8번 문제

9.8 다음의 내용을 포함하는 Date 클래스를 설계하여라

class에서

- 날짜를 표시하는 year, month, day 데이터 필드

- 현재 날짜에 대한 Date 객체를 생성하는 인수 없는 생성자

- 1970년 1월 1일 자정부터 지금까지의 경과 시간을 초로 나타내는 Date객체를 생성하는 생성자

- year, month, day 데이터 필드에 대한 세 개의 get 함수

- 경과 시간을 사용하여 객체에 대한 새로운 날짜를 설정하는 setDate(int elapseTime) 함수

 

main에서

- 인수없는 생성자 객체 생성

- Date(555550)를 사용하는 객체 생성

- 연, 월, 일을 화면에 출력

 


UML 다이어그램

화질 왜이래. 그래도 글씨는 보이니까..
 
 

코드

#include <ctime>
#include <iostream>
using namespace std;

class Date
{
private:
	int year;
	int month;
	int day;

public:
	// 현재 날짜에 대한 객체
	Date() {
		setDate(time(0));
	}

	// 지정된 연, 월, 일을 갖는 Date객체를 생성하는 생성자
	Date(int newYear, int newMonth, int newDay)
	{
		year = newYear;
		month = newMonth;
		day = newDay;
	}

	// 1970.1.1 자정부터 지금까지의 경과시간을 초로 나타내는 Date객체를 생성하는 생성자
	Date(int totalSeconds)
	{
		setDate(totalSeconds);
	}

	// 함수
	// get함수
	int getYear() {
		return year;
	}
	int getMonth() {
		return month;
	}
	int getDay() {
		return day;
	}
	
	// 경과 시간(초)을 사용해 현재 날짜를 계산하는 함수
	void setDate(int elapseTime)
	{
		int totalSeconds = elapseTime;
		int totalDays = totalSeconds / 86400;
		int midYears = totalDays / 365; // 윤년이 포함되지 않은 햇수

		// 윤년이 포함된 수만큼 totalDays--하기: 윤년구분없이 365로 나누기 위해
		for (int i = 1970; i <= 1970 + midYears; i++)
		{
			if (i % 4 == 0) {
				if (i % 100 == 0 && i % 400 != 0)
					continue;
				else
					totalDays--;
			}
		}
		int totalYears = totalDays / 365; // 윤년이 계산된 햇수
		int restDays = totalDays % 365;
		// 달(월) 계산
		int count = 1;
		while (restDays >=28) {
			if (count == 1 || count == 3 || count == 5 || count == 7 || count == 8 || count == 10 || count == 12)
				restDays -= 31;
			else if (count == 2)
				restDays -= 28;
			else if (count == 4 || count == 6 || count == 9 || count == 11)
				restDays -= 30;
			else
				break;
			count++;
		}
		year = 1970 + totalYears;
		month = count;
		if (totalSeconds % 86400 > 0)
			day = ++restDays;
		else
			day = restDays;
	}
};

int main()
{
	Date date1(555550);
	Date dateNow;

	cout << "현재 날짜는: " << dateNow.getYear() << " / " << dateNow.getMonth() << " / " << dateNow.getDay() << endl;
	cout << "경과시간 555550초의 날짜는: " << date1.getYear() << " / " << date1.getMonth() << " / " << date1.getDay() << endl;

	return 0;
}

작성자는 구조체를 배우지 않은 시점.

구글링을 아무리 해 봐도 구조체를 사용하지 않고 time(0)을 이용해 현재 날짜를 생성하는 방법은 찾지 못 했다.

결국 윤년을 공부해 직접 만들었다.

 

윤년이란?

지구는 약 1년간 한 바퀴 공전을 하는데, 이 시간이 365일보다 더 오래 걸린다. 따라서 4년이 지나면 오래 걸리는 시간이 모여 약 하루치가 되는데, 이 시간을 적용한 달이 윤달이고 윤달이 포함된 해가 윤년이다.

 

- 윤년의 2월에는 하루가 늘어 29일이 된다.

- 윤년은 4로 나누어 떨어지는 해이므로 4년마다 돌아온다

- 윤년 중, 100으로 나누어 떨어지고 400으로 나누어 떨어지지 않는 해는 제외한다

- 윤년은 366일이다

 

정리하면 이러하다.

 

주요 코드리뷰 setDate(int elapseTime)

경과 시간(초)을 이용해 날짜를 계산하는 함수는 setDate(int elapseTime) 이다

나는 임시적으로 햇수를 365로 나눠 midYears에 넣었다.

그리고 for문을 통해 1970년+midYears에 포함된 윤년의 수만큼 totalDays에서 하루씩 뺐다.

이 과정을 한 이유는 for문 후에 totalDays에서 윤년을 고려하지 않고 1년을 365로 고려해 나누기 위해서이다.

따라서 midYears는 윤년이 적용되지 않은 햇수, totalYears는 윤년이 적용된 햇수이다.

 

while문은 보이다시피 달을 계산한다.

직관적으로 count=1이면 1월이 되도록 설정했다.

 

마지막 if문

만약 totalSeconds를 86400초(24시간)로 나누어 나머지가 발생한다면 그 다음날이 되기 때문에 넣었다.

연산자 /은 몫이므로 totalDays = totalSeconds / 86400 에선 남은 초가 고려되지 않기 때문이다.

 


실행  결과

실행 당시 날짜는 2023/3/20 이었다

 

만약 코드가 틀렸거나 더 나은 방식/의견이 있다면 댓글 환영합니다 :D