11// eslint-disable-next-line -- TODO: move to date-fns
22import moment from 'moment' ;
33import { TimeResult } from '../types' ;
4+ import { defaultZoneOffset } from './zoneOffsets' ;
45
56const ZONE_RX = / ( Z | [ + - ] \d { 2 } [: + ] ? \d { 2 } ) $ / ;
67
7- function startOfToday ( format : string ) {
8- return moment ( ) . set ( { hours : 0 , minutes : 0 } ) . format ( format ) ;
9- }
10-
118function fieldValueToMoment ( datetimeString : string | null | undefined ) : moment . Moment | null {
129 if ( ! datetimeString ) {
1310 return null ;
@@ -42,9 +39,15 @@ function datetimeFromUserInput(input: TimeResult): {
4239 }
4340
4441 const time = timeFromUserInput ( input ) ;
42+ let utcOffset = input . utcOffset ;
43+
44+ // If we have the default local offset, compute the local offset for the specified date
45+ if ( utcOffset === defaultZoneOffset ) {
46+ utcOffset = computeLocalZoneOffset ( input . date , time ) ;
47+ }
4548
4649 const date = moment
47- . parseZone ( input . utcOffset , 'Z' )
50+ . parseZone ( utcOffset , 'Z' )
4851 . set ( input . date . toObject ( ) )
4952 . set ( { hours : time . hours ( ) , minutes : time . minutes ( ) } ) ;
5053
@@ -93,7 +96,31 @@ export function getDefaultAMPM() {
9396}
9497
9598export function getDefaultUtcOffset ( ) {
96- return startOfToday ( 'Z' ) ;
99+ return defaultZoneOffset ;
100+ }
101+
102+ /**
103+ * Compute the local zone offset for the specified date and time.
104+ *
105+ * Creates a new local-mode moment from the calendar date/time components so
106+ * that format('Z') returns the machine's local timezone offset (DST-aware),
107+ * regardless of whether `date` carries a fixed UTC offset.
108+ *
109+ * @param date - The moment object for the date
110+ * @param time - Optional moment with time
111+ * @returns The offset as a string (e.g., "-08:00", "+05:30")
112+ */
113+ export function computeLocalZoneOffset ( date : moment . Moment , time ?: moment . Moment ) : string {
114+ const localMoment = moment ( {
115+ year : date . year ( ) ,
116+ month : date . month ( ) ,
117+ date : date . date ( ) ,
118+ hour : time ? time . hour ( ) : 0 ,
119+ minute : time ? time . minute ( ) : 0 ,
120+ second : 0 ,
121+ millisecond : 0 ,
122+ } ) ;
123+ return localMoment . format ( 'Z' ) ;
97124}
98125
99126/**
@@ -109,12 +136,17 @@ export function userInputFromDatetime({
109136 const datetime = fieldValueToMoment ( value ) ;
110137
111138 if ( datetime ) {
139+ let utcOffset = datetime . format ( 'Z' ) ;
140+ const localOffset = computeLocalZoneOffset ( datetime ) ;
141+ if ( utcOffset === localOffset ) {
142+ utcOffset = defaultZoneOffset ;
143+ }
112144 const timeFormat = uses12hClock ? 'hh:mm' : 'HH:mm' ;
113145 return {
114146 date : datetime ,
115147 time : datetime . format ( timeFormat ) ,
116148 ampm : datetime . format ( 'A' ) ,
117- utcOffset : datetime . format ( 'Z' ) ,
149+ utcOffset : utcOffset ,
118150 } ;
119151 } else {
120152 return {
0 commit comments