[Rails] TimeZone 알아보기
Timezone 날짜 계산
시간은 중요하다. 특히 글로벌한 서비스를 구성할 예정이라면 더욱 중요한 요소이다. 그 외에도 서비스 중 시간, 날짜 계산이 필요한 경우 Timezone에 대해서 생각하기 시작한다. 타임존을 설정하면 사용자의 지역에 따라 해당하는 시간을 보여주거나 연산이 가능하다.
Rails에서 Timezone 설정하기
rails에서 TimeZone을 설정하는 경우 생각해야하는 요소는 두 가지이다. time_zone, active_record의 타임존 설정인데, Rails 시간을 보여주는 설정과 액티브 레코드 설정으로 실제 데이터 베이스에 지정되는 타임존이다. 설정하지 않으면 default로 utc가 들어간다.
- config.time_zone
- config.active_record.default_timezone
각각 한국 시간대로 설정한다고 가정하고 작성하면 다음과 같다. 이 경우, 데이터 베이스에 저장되는 값은 local의 값, 실제로 rails에서 보여지는 값은 서울 시간대이다.
config.time_zone = ‘Seoul’
config.active_record.default_timezone = :local #utc
설정한 후 확인하기 위해 아래 명령어를 작성하면, 리스트에 우리가 설정한 seoul이 있는지 확인하자. 있다면 잘 설정된 것이다.
rails time:zones:all
다른 나라에 대한 시간은 아래 참고자료를 참고 하자.
- 참고자료
[ Ruby on Rails ] 시간대 서울로 맞추기 ( Timezone Seoul )
시간 계산하기
설정이 끝났다면, 해당 시간에 따른 계산을 할 수 있다. 만약 config.time_zone을 하지 않았다면, ActiveSupport::TimeWithZone
인스턴스를 생성해야 한다. 하지만, 설정을 했다면, Time.zone을 통해 쉽게 연산할 수 있다.
어제, 오늘, 내일
어제 : Time.zone.yesterday
오늘 : Time.zone.now
내일 : Time.zone.tomorrow
지정한 시간 : Time.zone.parse(’2021-01-13 12:00:00’)
# 시각, 날짜, 년도만 쓸 수도 있음.
포멧팅 : Time.zone.strptime('1999-12-31 14:00:00', '%Y-%m-%d %H:%M:%S')
지정한 시간, 포멧팅에 str 부분이 잘못되었다면 ArgumentError가 발생한다. 만약 해당 날짜에서 초, 분, 시간, 날짜, 주, 달, 년도 를 더하는 경우 advance를 이용하면 된다. 빼는 경우는 ago를 사용한다. 해당 내용 중 일부를 바꾸는 경우 change를 이용할 수 도 있다.
time = Time.zone.now
# advance 더하기
time.now.advance(days: 1) # 하루 더해진다.
time.now.advance(weeks: 2) # 2주 더해진다.
# ago 빼기
time.now.ago(1.day) # 하루 뺀다.
time.now.ago(2.weeks) # 2주 뺀다.
# change 요소 바꾸기
time.change(hour: 11) # 시간이 11시가 된다.
time.change(zone: "utc") # 해당 객체의 타임존을 바꾼다.
10.days.ago # now가 default인 것 같다.
테스트에서 시간 조종하기
rails 테스트에서 특정 시간에 대해서 설정하고 싶은 경우, Rails time helper를 이용하거나 Timecop을 많이 이용한다. 개인적으로 TimeHelper보다는 Timecop이 더 간편하고 사용하기 쉽다.
Timecop과 Timehelper의 차이는 Timecop에는 scale 메소드가 있지만, Timehelper에는 해당 메소드가 없다는 것이다. scale은 아래의 Timecop 과 같이 원하는 값 만클 시간을 흐르게 조정할 수 있다.
helper를 이용하면 단순히 어느 시점의 시간으로 고정을 시키거나, travel을 통해서 다시 설정을 해야하는 등의 번거로움이 있기 때문에, 시간이 중요한 테스트에서 더 유연하게 조절하기 위해서는 Timecop 사용이 더 좋다고 할 수 있다. 또한, Timecop의 경우 safemode, 블록 단위에 설계가 가능하기 때문에 Timecop을 더 선호한다.
차이점
Timehelper | Timecop | |
---|---|---|
freeze | Timehelper.freeze | Timecop.freeze |
travel | Timehelper.travel_to | Timecop.travel |
scale | 없음 | Timecop.scale |
Timecop
시간을 사용해야할 때는 주로 테스트에서 일어난다. rspec에서 주로 Timecop을 이용한다. Timecop은 간단하다.
- Timecop.freeze : 지정된 시간에 멈추기 (지정한 시간으로 고정)
- Timecop.travel : 지정된 시간으로 설정 (설정 후 시간이 흐름)
- Timecop.scale : 시간 흐르기 (원하는 값 만큼 시간이 흐름)
이렇게 시간을 조종하면, Timecop.return으로 초기화해주어야한다. 만약 블록 형식(safe_mode)로 작성된 경우 따로 지정하지 않아도 해당 블록 이후에 초기화 된다.
# not_safe mode
Timecop.freeze(...)
Timecop.return
# safe_mode
Timecop.freeze(...) do
...
end
만약 Timecop.safe_mode = true
으로 두면 무조건 블록 형식으로 작성하여야 동작한다.
Leave a comment