Calendar 클래스

Calendar 클래스는 날짜와 시간을 다루기 위해서 Date와 함께 많이 쓰이는 클래스 중 하나입니다. Calendar를 사용하기 위해서는 java.util.Calendar를 import 시켜야합니다. 

가장 기본적으로 현재 날짜와 시간을 가져올 수도 있고, 특정 시간으로 시간을 되돌리거나 뒤로갈 수도 있습니다. 이는 Calendar에서 제공하는 상수들을, 예를 들면 YEAR, MONTH, DAY_OF_MONTH 등을 이용하여 설정할 수 있습니다. 어떤 필드가 있는지 볼까요? 아래의 필드를 이용해서 get, set 메소드를 통해 값을 얻어오거나 설정할 수 있습니다.

Field(static int) 설명
YEAR 년도를 나타냅니다.
MONTH 월을 나타내는데, 이때 1월을 상수 0으로 대응이 됩니다. 그래서 실제 월을 구할때는 +1을 해주어야합니다.
DATE, DAY_OF_MONTH 월의 날짜를 의미합니다.
DAY_OF_WEEK 일주일에 해당되는 요일을 의미합니다. 일요일부터 시작이며 일요일은 1입니다. 수요일은 4의 값을 갖습니다.
HOUR 시간을 표시하는데 12시간 단위의 시간을 의미합니다.
HOUR_OF_DAY 시간을 표시하는데 24시간 단위의 시간을 의미합니다.
MINUTE 분을 의미하는 필드입니다.
SECOND 초를 의마하는 필드입니다.
MILLISECOND 밀리 세건드 단위를 의미하는 필드입니다.

 

아래의 필드는 get, set으로 얻지는 않고 비교할때 사용할 수 있습니다.

Field(static int) 설명
JANUARY 1월을 나타냅니다. 0의 값을 갖고 있습니다.
월을 나타내는 필드는 전부 대문자입니다. 2월을 FEBURARY, 3월은 MARCH입니다. 각 숫자는 월-1에 값을 갖습니다.
SUNDAY 일요일에 해당하는 값이며 1을 가집니다. 요일을 나타내는 상수도 마찬가지로 전부 대문자로 표시할 수 있으며 SUNDAY의 1부터 SATURDAY의 7까지 나타낼 수 있습니다.

 

이번 포스팅에서는 Calendar클래스를 어떻게 사용하고 다루는지 예를 통해서 설명하도록 하겠습니다.

1. 현재 시간의 정보를 표시하는 예제

    public static void main(String[] args){
    	Calendar cal=Calendar.getInstance();	//getInstance()로 객체 생성
    	System.out.println("현재 날짜:"+cal.get(Calendar.YEAR)+"-"+(cal.get(Calendar.MONTH)+1)+"-"+cal.get(Calendar.DAY_OF_MONTH));
    	System.out.println("일주일 중 오늘은 "+cal.get(Calendar.DAY_OF_WEEK)+"번째 요일 (1은 일요일)");
    	System.out.println("일년 중 오늘은 "+cal.get(Calendar.DAY_OF_YEAR)+"번째 날");
    	System.out.println("현재 시간 "+cal.get(Calendar.HOUR_OF_DAY)+":"+cal.get(Calendar.MINUTE)+":"+cal.get(Calendar.SECOND)+":"+cal.get(Calendar.MILLISECOND));
    	System.out.println("현재 시간 "+cal.get(Calendar.AM_PM)+":"+cal.get(Calendar.MINUTE)+":"+cal.get(Calendar.SECOND));
    	System.out.println("이번 주는 일년 중 "+cal.get(Calendar.WEEK_OF_YEAR)+"번째 주");
    }

 

Calendar객체는 new 키워드로 객체를 생성할 수 없고 getInstance() 메소드로 객체를 생성할 수 있습니다. 위 예제는 현재 날짜와 시간을 나타내며 위에 설명한 표의 데이터가 어떤 값을 나타내는 지 확인하는 예제입니다.

현재 날짜:2021-10-20
일주일 중 오늘은 4번째 요일 (1은 일요일)
일년 중 오늘은 293번째 날
현재 시간 19:36:39:959
현재 시간 1:36:39
이번 주는 일년 중 43번째 주

 

2. set 메소드로 날짜 설정

    public static void main(String[] args){
    	Calendar cal=Calendar.getInstance();	//getInstance()로 객체 생성. 기본 현재 날짜
    	cal.set(Calendar.MONDAY,Calendar.DECEMBER); 	//12월로 설정
    	cal.set(Calendar.HOUR_OF_DAY,14);	//오후 2시로 Calendar 객체 설정
    	System.out.println("설정된 날짜 - "+(cal.get(Calendar.MONTH)+1)+"월 "+cal.get(Calendar.DATE)+"일");
    	System.out.println("설정된 시간 - "+cal.get(Calendar.HOUR_OF_DAY)+":"+cal.get(Calendar.MINUTE)+":"+cal.get(Calendar.SECOND));
    	
    }

 

이번에는 set 메소드로 month와 hour를 설정해보았습니다. 아래처럼 원래의 date와 minute, second는 현재의 시간과 동일하며 month와 hour만 바뀐 것을 알 수 있네요.

설정된 날짜 - 12월 20일
설정된 시간 - 14:43:55

 

이렇게 개별적으로 바꿀 수도 있습니다만, 만약 한꺼번에 바꾸고 싶다고 하면 오버로딩된 set메소드를 활용하시면 됩니다.

    public static void main(String[] args){
    	Calendar newYear=Calendar.getInstance();
    	newYear.set(2022,Calendar.JANUARY,1);	//년, 월, 일 설정
    	System.out.println(newYear.get(Calendar.YEAR)+"년 "+(newYear.get(Calendar.MONTH)+1)+"월 "+newYear.get(Calendar.DATE)+"일");
    	
    	newYear.set(2022,Calendar.JANUARY,1,0,0);	//년, 월, 일, 시, 분 설정
    	System.out.println(newYear.get(Calendar.YEAR)+"년 "+(newYear.get(Calendar.MONTH)+1)+"월 "+newYear.get(Calendar.DATE)+"일");
    	System.out.println(newYear.get(Calendar.HOUR_OF_DAY)+"시 "+newYear.get(Calendar.MINUTE));
    }
2022년 1월 1
2022년 1월 1
0시 0

 

3. 밀리초로 1970년 1월 1일 00시 00분부터 흐른 시간 구하기

    public static void main(String[] args){
    	Calendar today=Calendar.getInstance();	//getInstance()로 객체 생성. 기본 현재 날짜
    	System.out.println("1970년 00시 00분부터 흐른 초 :"+today.getTimeInMillis()/1000);
    	
    	SimpleDateFormat format=new SimpleDateFormat("a hh:mm:ss");	
    	System.out.println("현재시간 "+format.format(today.getTimeInMillis()));	//SimpleDateFormat으로 출력
    	
    	
    	Calendar newYear=Calendar.getInstance();	//현지 시간으로 설정
    	newYear.set(Calendar.YEAR, 2021);
    	newYear.set(Calendar.MONTH, Calendar.OCTOBER);
    	newYear.set(Calendar.DAY_OF_MONTH, 21);
    	
    	long diff=newYear.getTimeInMillis()-today.getTimeInMillis();
    	Calendar dDay=Calendar.getInstance();
    	dDay.setTimeInMillis(diff);	//1년 이내로만 이 코드를 쓸 수 있음
    	System.out.println("남은 날 수 :"+(dDay.get(Calendar.DAY_OF_YEAR)-1));	//오늘이 포함되므로 -1
    	
    	diff=diff/(60*60*24*1000);	//60(분) * 60(1분) * 24(시간) * 1(초) = 하루 
    	System.out.println("남은 날 수 :"+diff);
    }

 

getTimeInMillis를 통해서 밀리초단위로 구할 수 있습니다. 밀리초 단위로 SimpleDateFormat에 설정하여 더 쉽게 볼 수도 있고, 두 시간 사이의 계산도 가능합니다. 

1970년 00시 00분부터 흐른 초 :1634727499
현재시간 오후 07:58:19
남은 날 수 :2
남은 날 수 :1

 

4. 특정 날짜가 현재 날짜보다 전날인지, 이후인지 확인

    public static void main(String[] args){
    	Calendar yesterday=Calendar.getInstance();
    	yesterday.set(Calendar.DATE, yesterday.get(Calendar.DATE)-1);	//현재 날짜 -1로 설정
    	Calendar today=Calendar.getInstance();
    	
    	Calendar tomorrow=Calendar.getInstance();
    	tomorrow.set(Calendar.DATE, tomorrow.get(Calendar.DATE)+1);	//현재 날짜 +1
    	
    	System.out.println("오늘이 어제보다 이전인가? "+today.before(yesterday));
    	System.out.println("오늘이 내일보다 이전인가? "+today.before(tomorrow));
    	
    	System.out.println("오늘이 어제보다 이후인가? "+today.after(yesterday));
    	System.out.println("오늘이 내일보다 이후인가? "+today.after(tomorrow));
    }

위 코드는 어제와 내일로 일단 날짜를 지정한 Calendar객체로 오늘이 앞날인지, 뒷날인지 비교하는 코드입니다. 

오늘이 어제보다 이전인가? false
오늘이 내일보다 이전인가? true
오늘이 어제보다 이후인가? true
오늘이 내일보다 이후인가? false

 

또한 위의 코드는 아래와 같이 add 메소드를 활용하는 방식으로 바꿀 수도 있습니다.

    	Calendar yesterday=Calendar.getInstance();
    	yesterday.set(Calendar.DATE, -1);
    	Calendar today=Calendar.getInstance();
    	
    	Calendar tomorrow=Calendar.getInstance();
    	tomorrow.add(Calendar.DATE,1);

 

이상으로 Calendar 클래스의 활용과 예제를 살펴보았습니다.

 

반응형
블로그 이미지

REAKWON

와나진짜

,

리눅스의 특수 권한(setuid, setgid, sticky) 외에 더 많은 정보와 예제를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

실행권한

리눅스에서 파일을 다루는 방법은 세가지가 있습니다. 파일을 읽고(read), 쓰고(write), 실행(execute)하는 것이 그 세가지입니다. 리눅스는 서버용 멀티유저 운영체제이기 때문에 권한이 매우 중요합니다. 어떤 관리자는 특정 파일에 대해서 읽고 쓸 수 있는 권한이 있을 수 있고, 다른 관리자는 수정이 불가한 파일이 있을 수가 있겠죠. 이렇게 파일을 다룰 수 있게 리눅스에서는 파일의 속성을 줄 수가 있습니다. 

ls -l 명령으로 exam.txt파일의 실행권한을 보도록 하겠습니다.

노란색으로 표시한 부분이 이 파일의 권한을 의미합니다. 이 파일을 만든 소유자는 ubuntu이고 ubuntu라는 그룹이라는 것도 알 수 있습니다.

-rw-rw-r--

- r w - r w - r - -
파일 종류
-는 일반 정규 파일
소유자의 read 권한 소유자의 write권한 소유자의 실행권한 X 소유자 그룹의 read권한 소유자 그룹의 write권한 소유자 그룹의 실행권한X 다른 사용자의 read권한 다른 사용자의 write권한X 다른 사용자의 실행권한X

 

맨앞의 파일의 종류를 나타내는 '-'를 제외하고 권한의 '-'는 그 파일에 대한 해당 권한이 없다는 것을 의미합니다. 권한은 아까 세종류가 있다고 했는데 각각 이렇습니다.

r read로 파일을 읽을 수 있는 권한입니다.
w write로 파일을 수정할 수 있는 권한입니다.
x execute로 파일을 실행할 수 있는 권한입니다. 파일에는 단순 기록하는 파일외에도 실행파일이 있기 때문에 이러한 권한이 필요합니다.

 

chmod 명령어

chmod는 파일의 권한을 바꿀 수 있는 명령어입니다. 명령어 형식은 이렇습니다.

chmod [파일에 추가거나 뺄 권한] [파일 이름]

만일 다른 유저들의 쓰기 권한을 추가하고 싶다면 아래의 명령으로 권한을 추가할 수 있습니다. 

 

u+w의 앞 u는 사용자를 의미합니다. 여기서 +는 더한다는것을 알 수 있겠죠? 반대로 뺄때는 -를 씁니다. 마지막 글자 w는 어떤 권한인지를 말합니다. 읽기 권한을 추가하려면 r를 사용하면 되겠네요. 맨 처음 글자는 아래와 같습니다. 

u user의 앞글자로 소유자를 의미합니다.
g group의 앞글자로 소유자의 그룹을 의미합니다.
o other의 앞글자로 다른 유저들을 의미합니다.

 

여러 권한을 설정할때는 쉼표로 나열해주면 됩니다. 아래는 그룹과 다른 유저들에게 r,w를 더해주는 명령어의 예입니다.

chmod g+rw,o+rw file.txt

그리고 숫자로 권한을 일괄적으로 바꾸는 방법도 있습니다.

파일의 권한을 설명할때 rwxrwxrwx로 해도되지만 보통은 정수를 사용하여 권한을 이야기합니다. 앞에 rw-rw-r--는 숫자 664로 대응이 되는데, 왜 이렇게 되는걸까요? 세개를 묶어서 세비트로 표현하기 때문입니다.

r w - r w - r - -
1 1 0 1 1 0 1 0 0
4 2 0 4 2 0 4 0 0

두번째 줄은 이진수, 세번째 줄은 10진수로 표현했습니다. 그래서 rw-는 결국 이진수 110으로 되어 6이 됩니다. 그렇다면 rwx는 111이 되어서 7이겠네요.

아래는 chmod로 유저는 모든 권한을, 그룹 사용자는 읽기, 쓰기 권한을, 그리고 다른 사용자는 읽기 권한만 추가하는 명령어의 예입니다.

- chmod 764 a.out

그리고 setuid와 setgid, sticky의 비트를 사용하여 네자리로 표현할 수도 있습니다. 각각 setuid는 4, setgid는 2, sticky는 1로 대응이됩니다.

- chmod 4764 a.out

위 명령은 setuid를 설정하는 명령입니다. setuid와 setgid, sticky는 아래에 설명하도록 하겠습니다.

 

setuid

setuid를 설명하기에 앞서 리눅스에서는 유저를 id로 구별합니다. 두 종류가 있는데 아래와 같습니다.

UID (REAL UID) : 이는 실제 사용자 본인의 아이디를 표현한다고 해서 real id라고도 하면 uid라고 합니다. 

EUID (EFFECTIVE UID) : 유효 사용자 아이디라고해서 프로그램이 실행될때 갖는 아이디를 말합니다. 즉, 실행시에 이 프로그램을 만든 사용자의 ID로 실행이 된다는 겁니다. 

setuid의 예1)

그렇다면 setuid의 예를 하나 들어보도록 할까요? 아래와 같이 root가 파일 하나를 만들고 본인만 읽을 수 있게 만들어 놓았습니다.

 

그리고 root 사용자는 아래와 같은 코드로 이 파일을 읽는 코드를 짜서 실행파일을 만들었습니다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(){
        int fd=open("root_read_only.txt",O_RDONLY);
        int n;
        char buf[128];
        printf("uid:%d\n",getuid());    //실제 사용자 ID
        printf("euid:%d\n",geteuid());  //이 프로그램을 실행할때만 갖는 ID
        n=read(fd,buf,sizeof(buf));
        if(n<0){
                printf("파일을읽을 수 없습니다. erorr code:%d\n",n);
                exit(1);
        }
        printf("file content:%s\n",buf);
}

 

root 사용자가 이 실행파일의 주인이고 실행파일의 권한은 모든 사용자가 실행할 수 있게 만들었습니다. 

 

이제 다른 사용자인 ubuntu가 이 read.out이라는 실행파일을 실행하게 되면 아래의 내용과 같이 나옵니다. 지금 현재 uid는 1000이고 euid도 1000이라서 root_read_only.txt를 볼 수 없습니다. 왜냐면 root_read_only.txt는 오직 root만 읽을 수 있게 설정했거든요. 

 

이때 이 실행파일이 실행될때만 루트의 권한을 갖도록 하여 파일을 읽을 수 있게 하는 방법은 euid를 root로 설정하는 setuid를 주면 될텐데요. root 계정으로 그 권한을 줘보도록 하겠습니다. chmod u+s read.out으로 setuid를 줄 수 있고, 이때 rwsrwxrwx로 바뀌게 된것을 알 수 있습니다. 소유자의 실행권한인 s로 바뀐 것은 setuid가 설정되어 있는 파일이며 실행시에 파일의 소유자의 권한으로 실행된다는 것을 의미합니다.

 

이제 ubuntu라는 유저는 이 root_read_only.txt라는 파일을 읽을 수 있을까요? 그럴 수 있는지 read.out을 실행해보도록 합시다. 

 

euid가 0으로 바뀐것을 확인할 수 있으면서 file의 내용을 읽어볼 수 있습니다.

setuid의 예2)  passwd

setuid를 설명하기 위해서 임의로 제가 만든 하나의 예입니다. 리눅스에서 가장 대표적으로 setuid를 사용하는 실행파일은 /bin/passwd파일입니다. 이 파일은 사용자의 비밀번호를 바꾸는데, 필요한 명령어로 /etc/passwd를 수정해야합니다. 하지만 /etc/passwd는 절대 root만 수정할 수 있으므로 다른 사용자는 변경할 수가 없죠. 그렇지만 다른 사용자들이 비밀번호를 바꿀때 /etc/passwd를 수정해야하므로 수정 프로그램이 필요하고 그 파일이 바로 /bin/passwd파일입니다. /bin/passwd는 실행시에 루트권한으로 실행이되어 /etc/passwd파일을 수정할 수 있게 됩니다.

 

 

setgid

setgid 역시 비슷합니다. 실행시에 그룹의 권한을 갖는 다는 것인데요. 앞서 설명한 setuid와 개념은 비슷하며 그룹 권한에 s로 표시가 됩니다. 

 

sticky비트

sticky비트는 다른 사용자가 자유롭게 디렉토리를 사용할 수 있도록 만드는 권한입니다. 원래 디렉토리도 디렉토리를 만든 사람만이 읽기, 쓰기가 가능합니다. 하지만 sticky를 쓰면 모든 사용자가 자유롭게 읽기, 쓰기가 가능합니다. 마치 공유폴더와 아주 비슷한 개념입니다. 이 권한은 디렉토리에만 해당되는 권한입니다. 예를 들어설명해볼까요?

아래와 같이 root는 공유폴더를 만들 목적으로 디렉토리를 하나 만들었습니다. 하지만 권한을 주지는 않았죠. 

 

그래서 ubuntu라는 유저는 이 디렉토리에 파일을 기록하려고 했으나 아래와 같이 권한이 없다는 메시지를 받게 됩니다.

 

아래와 같이 root는 다른 유저에 대해서 sticky비트를 설정합니다.

 

이렇게 되면 아래와 같이 ubuntu는 /shared 디렉토리를 자유롭게 이용할 수 있습니다.

 

여기까지 리눅스 파일의 실행권한과 setuid, setgid, sticky에 대한 개념을 알아보았습니다. 최대한 쉽게 예를 들어 설명하려고 했는데, 이해가 가셨는지 모르겠네요. 

반응형
블로그 이미지

REAKWON

와나진짜

,