뚜벅이

(Salesforce/APEX) Timezone handling 본문

세일즈포스

(Salesforce/APEX) Timezone handling

ZZM 2025. 4. 8. 15:10
반응형

미쳐버릴 뻔한 현상공유.

KK 유저 ( Timezone이 Asia/Seoul ) 인 유저로, 현 시점의 NN (America/Los_Angeles) 시간대의 date 즉 날짜값만을 뽑아서 return 해주고 싶은 목표가 있었음.

근데 하기 로직으로는. 도저히 출력이 안되고, 계속 현재 apex run 하는 유저의 timezone 날짜값 yyyy-mm-dd 를 가져오는 것이 확인됨.

code 1 참조 .

code 1 실패 건.

DateTime utcNow = System.now();  
System.debug('@@utcNow@@ : ');  
System.debug(utcNow);  
TimeZone properTz = TimeZone.getTimeZone('America/Los\_Angeles');  
Datetime americanDateTime = utcNow.addSeconds(properTz.getOffset(utcNow) / 1000);  
System.debug('Lets print Datetime ^^ : ');  
System.debug(americanDateTime);

Date notMyLocalDate = utcNow.addSeconds(properTz.getOffset(utcNow) / 1000).date();  
System.debug('Lets print Date ^^ : ');  
System.debug(notMyLocalDate);  
System.debug('왜 갑자기 UTC date ?? ');  

anonymous apex output


15:25:40.60 (60696765)|CODE\_UNIT\_STARTED|\[EXTERNAL\]|execute\_anonymous\_apex

15:25:40.60 (61382466)|USER\_DEBUG|\[3\]|DEBUG|@@utcNow@@ :

15:25:40.60 (61409421)|USER\_DEBUG|\[4\]|DEBUG|2025-04-08 06:25:40

15:25:40.60 (73297650)|USER\_DEBUG|\[7\]|DEBUG|Lets print Datetime ^^ :

15:25:40.60 (73329753)|USER\_DEBUG|\[8\]|DEBUG|2025-04-07 23:25:40

15:25:40.60 (73688450)|USER\_DEBUG|\[11\]|DEBUG|Lets print Date ^^ :

15:25:40.60 (73708355)|USER\_DEBUG|\[12\]|DEBUG|2025-04-08 00:00:00

15:25:40.60 (73719494)|USER\_DEBUG|\[13\]|DEBUG|왜 갑자기 UTC date ??

GPT 에게 개선 요청해봐도 .가 아니라 요청하니 대박 났네. 근데 GPT 는 addMilliseconds 가 있을거라 기대하고 이 함수로 코드 짰으나 실제로 없었음. 그러나 dev문서에 addSeconds 는 있길래 addSeconds 하고 변수에 1000나눔으로서 처리함.

DateTime utcNow = System.now(); // UTC-based DateTime  
System.debug('UTC Now: ' + utcNow);  
// Shift UTC by the proper LA offset  
DateTime calculatedDateTime = utcNow.addSeconds( TimeZone.getTimeZone('America/Los\_Angeles').getOffset(utcNow) / 1000);  
// Extract the date using formatGmt to avoid user timezone interference  
Date finalDate = Date.valueOf(calculatedDateTime.formatGmt('yyyy-MM-dd'));

System.debug('LA DateTime: ' + calculatedDateTime);  
System.debug('Final LA Date: ' + finalDate);  

String 뽑기 대작전 방법.

DateTime utcNow = System.now();  
System.debug('@@utcNow@@ : ');  
System.debug(utcNow);  
String request = 'North America';  
System.debug('@@REQUEST@@ : ' + request );  
System.debug(request == 'North America');  
String timeZoneStr;  
timeZoneStr ='America/Los\_Angeles';  
System.debug('@@timeZoneStr@@ : ' + timeZoneStr );  
TimeZone properTz = TimeZone.getTimeZone(timeZoneStr);  
Datetime resultDateValue = utcNow.addSeconds(properTz.getOffset(utcNow) / 1000);  
System.debug('@@resultDateValue @@@:'+resultDateValue);  
String dateStr = resultDateValue.formatGmt('yyyy-MM-dd');  
System.debug(dateStr);  
String\[\] parts = dateStr.split('-');  
String year = parts\[0\];  
String month = parts\[1\];  
String day = parts\[2\];  
System.debug('Year: ' + year + ', Month: ' + month + ', Day: ' + day);  
// 3. Convert to Date object (optional)  
Date dateOnly = Date.valueOf(dateStr);  
System.debug('Final Date Object: ' + dateOnly);  

원인은??

문제 생긴 부분은 역시 단 한줄이었음.
In this line:

```Java
Date notUTCDatePlease = utcNow.addSeconds(properTz.getOffset(utcNow) / 1000).date();
```

You're:

Taking System.now() (UTC),

Adding an offset in seconds (from TimeZone.getOffset()),

Then calling .date() — but .date() is based on the current user’s timezone, not the LA time you've calculated.

So even if your DateTime object holds 2025-04-07 21:59, if the current user's timezone is UTC+9 (e.g., Korea), .date() will reflect 2025-04-08.

결론 : .date() 함수를 함부로 썼다가 큰코 다친 경험이었다.

공식문서에서 봐도 datetime.date() 에 local time 이 뻔히 써져 있었다..

Returns the Date component of a Datetime in the local time zone of the context user.

어이없는 결말.

공식문서를 보다 date 함수 바로 아래 dateGMT 가 있었다.

https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_methods_system_datetime.htm#apex_System_Datetime_dateGMT

이게 description 에는 Return the Date component of a Datetime in the GMT time zone. 으로 써있긴한데, 그냥 addSeconds 상태 값을 그대로 가져오는것 같다. 즉 현재 보이는 datetime instance 값의 date 를 있는 그대로 터치없이 가져오는 것으로 확인되었다.

결국 code 1 에서 date() 가 아닌 dateGMT() 썼으면 끝났을 것인데......... 문자열 변환 쇼를 하면서 생난리를 친 경험이었다. 내탓을 하자면 date 함수를 안 읽은 탓이맞다.

물론 나는 뒤늦게 확인한 method 였지만, 1% 정도 남탓을 하자면 셀포가 공식문서에서 dateGMT() 의 정의를 똑바로 써놓지 않았던 점.

반응형