Flutter - 날짜 & 시간

2023. 11. 8. 08:58·Flutter
728x90

시나리오

  1. 백엔드의 데이터베이스에는 UTC 기준시로 날짜시각을 저장한다.
  2. 백엔드와 프론트엔드는 ISO-8601 표준 날짜시각 형식 문자열로 주고 받는다.
  3. UTC 기준 마이크로초를 제거한 ISO-8601 표준 형식 예시는 2022-06-24T10:37:34+00:00와 같다.
  4. 백엔드에서 생성한 날짜시각 객체는 이력, 로그와 관련된 경우가 많으므로 프론트엔드에서는 출력만 가능할 뿐 변경할 수 없다.
  5. 프론트엔드에서 생성한 날짜시각 객체는 사용자의 일정과 관련된 경우가 많으므로 백엔드에 저장 시 폼 검증이 상대적으로 느슨하다.

백엔드에서 날짜시각 문자열을 받아 출력해야 하는 경우

UTC 기준 ISO-8601 문자열을 객체로 만든다. DateTime.parse()

  final utc = DateTime.parse('2022-06-24T20:39:35+00:00');
  print(utc.toIso8601String());  // 2022-06-24T20:39:35.000Z
  print(utc.timeZoneName);  // UTC
  print(utc.timeZoneOffset);  // 0:00:00.000000

UTC 기준 객체를 지역시간 기준으로 변경한다. toLocal()

  final kst = utc.toLocal();
  print(kst.toIso8601String());  // 2022-06-25T05:39:35.000
  print(kst.timeZoneName);  // 한국 표준시
  print(kst.timeZoneOffset);  // 9:00:00.000000

프론트엔드에서 날짜시각 객체를 생성해 백엔드에 저장해야 하는 경우

DateTimePicker 등으로 사용자가 선택한 날짜시각으로 객체를 생성한다. DateTime(연, 월, 일, 시, 분, 초)

  final birthday = DateTime(2016, 2, 12);
  print(birthday.toIso8601String());  // 2016-02-12T00:00:00.000
  print(birthday.timeZoneName);  // 한국 표준시
  print(birthday.timeZoneOffset);  // 9:00:00.000000

DateTime(연, 월, 일, 시, 분, 초)로 객체를 만들 경우 지역시 기준으로 날짜시각 객체를 생성한다.

현재 날짜시각으로 객체를 생성한다. DateTime.now()

  final now = DateTime.now(); 
  print(now.toIso8601String());  // 2022-06-27T23:12:28.181
  print(now.timeZoneName);  // 한국 표준시
  print(now.timeZoneOffset);  // 9:00:00.000000

DateTime.now() 정적 메소드 호출로 현재 날짜시각 객체를 얻을 수 있다.

지역시 기준 날짜시각 객체를 UTC 기준 ISO-8601 문자열 만들기

다트에서 별도의 함수, 메소드를 지원하지 않으므로 직접 toIsoStringAware 같은 헬퍼 함수를 만들어 써야 한다.

String toIsoStringAware(DateTime dt) {
  final iso8601 = dt.toIso8601String().substring(0, 19);

  if (dt.isUtc) {
    return '$iso8601+00:00';
  } else {
    if (dt.timeZoneOffset.inHours >= 0) {
      return '$iso8601+${dt.timeZoneOffset.inHours.toString().padLeft(2, "0")}:00';
    } else {
      return '$iso8601-${dt.timeZoneOffset.inHours.toString().padLeft(2, "0")}:00';
    }
  }
}

위 헬퍼 함수 사용 예시이다.

  final utc = now.toUtc();  // 지역시 기준으로 UTC 기준으로 변환한다.
  print(utc.toIso8601String());  // 2022-06-27T14:35:35.213Z
  print(utc.timeZoneName);  // UTC
  print(utc.timeZoneOffset);  // 0:00:00.000000
  print(toIsoStringAware(utc));  // 2022-06-27T14:35:35+00:00

이제 2022-06-27T14:35:35+00:00 UTC 기준 ISO-8601 날짜시각 문자열을 백엔드 서버에 전송할 수 있다.

날짜시각 더하고 빼기

날짜시각 객체를 Duration 기간 객체로 더하고 뺄 수 있다.

  final now = DateTime.now();

  final threeHoursAgo = now.subtract(const Duration(hours: 3));  // 3시간 전
  final inHundredDays = now.add(const Duration(days: 100));  // 100일 후

  print(now);  // 2022-06-28 01:34:51.588
  print(threeHoursAgo);  // 2022-06-27 22:34:51.588
  print(inHundredDays);  // 2022-10-06 01:34:51.588

intl 패키지 지역화 출력

import 'dart:async';

import 'package:intl/intl.dart';
import 'package:intl/date_symbol_data_local.dart';

void main() async {
    final now = DateTime.now();

    // ISO-8601 문자열
    print(now.toIso8601String());  // 2022-06-28T11:25:39.000

    // 기본 라이브러리
    print(DateFormat('yyyy-MM-dd').format(now));  // 2022-06-28
    print(DateFormat('HH:mm:ss').format(now));  // 11:25:39

    // intl 초기화
    await initializeDateFormatting('ko_KR', null);

    // 한국어
    print(DateFormat.yMMMMd('ko').add_Hms().format(now));  // 2022년 6월 28일 11시 25분 39초
    print(DateFormat.yMMMMd('ko').add_jms().format(now));  // 2022년 6월 28일 오전 11:25:39
    print(DateFormat.yMd('ko').format(now));  // 2022. 6. 28.
    print(DateFormat.Hm('ko').format(now));  // 11:25
    print(DateFormat.jm('ko').format(now));  // 오전 11:25

    // 영어
    print(DateFormat.yMMMMd('en').add_Hms().format(now));  // June 28, 2022 11:25:39
    print(DateFormat.yMMMMd('en').add_jms().format(now));  // June 28, 2022 11:25:39 AM
    print(DateFormat.yMd('en').format(now));  // 6/28/2022
    print(DateFormat.Hm('en').format(now));  // 11:25
    print(DateFormat.jm('en').format(now));  // 11:25 AM
}

날짜형식 메소드를 호출하기 전에 Future<void> initializeDateFormatting([String? locale, String? ignored]) 메소드를 호출해서 반드시 초기화해야 한다. 최소한 하나의 로케일은 지정해야 하나 만약 locale, ignored 둘다 지정하지 않으면 모든 로케일을 불러온다.

Future로 반환하는 비동기 함수이므로 await로 기다린다.

Hm 형식은 시간이 두 자리수 0으로 패딩되지만 jm은 패딩되지 않는다. 단, 둘다 분은 또 두 자리수 0으로 패딩된다.

  • Hm: 01:02
  • jm: 오전 1:02 또는 1:02 AM

단순히 숫자 형식으로만 출력한다면 굳이 intl 패키지 없이 그냥 기본 라이브러리로 충분히 포맷팅 가능하다.

728x90
LIST

'Flutter' 카테고리의 다른 글

Flutter - abstract class  (0) 2023.11.08
Flutter - 화페 & 숫자  (0) 2023.11.08
Flutter - WebScoket  (2) 2023.11.07
Flutter - JWT  (1) 2023.11.07
Flutter - 동시성 , 병렬성 , 콜백함수  (0) 2023.11.07
'Flutter' 카테고리의 다른 글
  • Flutter - abstract class
  • Flutter - 화페 & 숫자
  • Flutter - WebScoket
  • Flutter - JWT
Mr. Joo
Mr. Joo
  • Mr. Joo
    삽질의 시작
    Mr. Joo
  • 전체
    오늘
    어제
    • 분류 전체보기 (177) N
      • Flutter (67)
      • Android (9)
      • Swift (4)
      • React (11)
      • 인공지능 (4)
      • CS (10)
      • 개발 뉴스 (69) N
      • IT 기기 (1)
      • 알면 유용한 정보 (2)
  • 인기 글

  • 태그

    개발 이슈
    Flutter
    뉴스 모음
    개발 뉴스
    앱 개발
    DART
    앱
    react
    android
    뉴스
    이슈
    오늘의 이슈
    오늘의 뉴스
    개발
    Flutter 기초
    기술 뉴스
    플러터
    앱개발
    Dart 기초
    기술
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
Mr. Joo
Flutter - 날짜 & 시간
상단으로

티스토리툴바