Skip to content

Commit b2212f7

Browse files
authored
Merge pull request #1151 from MenamAfzal/add/time-zone
Add/time zone
2 parents 97904f7 + 286c500 commit b2212f7

File tree

8 files changed

+173
-394
lines changed

8 files changed

+173
-394
lines changed

client/packages/lowcoder/src/comps/comps/dateComp/dateComp.tsx

Lines changed: 89 additions & 245 deletions
Large diffs are not rendered by default.

client/packages/lowcoder/src/comps/comps/dateComp/dateRangeUIView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export const DateRangeUIView = (props: DateRangeUIViewProps) => {
8282
<StyledAntdSelect
8383
options={timeZoneOptions.filter(option => option.value !== 'UserChoice')}
8484
placeholder="Select Time Zone"
85-
defaultValue={'Etc/UTC'}
85+
defaultValue={Intl.DateTimeFormat().resolvedOptions().timeZone}
8686
onChange={props?.onClickDateRangeTimeZone}
8787
/>
8888
</StyledDiv>

client/packages/lowcoder/src/comps/comps/dateComp/dateUIView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export const DateUIView = (props: DataUIViewProps) => {
7070
<StyledAntdSelect
7171
options={timeZoneOptions.filter(option => option.value !== 'UserChoice')}
7272
placeholder="Select Time Zone"
73-
defaultValue={'Etc/UTC'}
73+
defaultValue={Intl.DateTimeFormat().resolvedOptions().timeZone}
7474
onChange={props.onClickDateTimeZone}
7575
/>
7676
</StyledDiv>

client/packages/lowcoder/src/comps/comps/dateComp/timeComp.tsx

Lines changed: 61 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import _ from "lodash";
22
import dayjs from "dayjs";
3-
import utc from 'dayjs/plugin/utc';
4-
import timezone from 'dayjs/plugin/timezone';
5-
import customParseFormat from 'dayjs/plugin/customParseFormat';
63
import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core";
74
import {
85
BoolCodeControl,
@@ -58,9 +55,6 @@ import { EditorContext } from "comps/editorState";
5855
import { dropdownControl } from "comps/controls/dropdownControl";
5956
import { timeZoneOptions } from "./timeZone";
6057

61-
dayjs.extend(utc);
62-
dayjs.extend(timezone);
63-
dayjs.extend(customParseFormat);
6458

6559
const EventOptions = [changeEvent, focusEvent, blurEvent] as const;
6660

@@ -90,7 +84,7 @@ const commonChildren = {
9084
),
9185
inputFieldStyle: styleControl(DateTimeStyle, 'inputFieldStyle'),
9286
suffixIcon: withDefault(IconControl, "/icon:regular/clock"),
93-
timeZone: dropdownControl(timeZoneOptions, "Etc/UTC"),
87+
timeZone: dropdownControl(timeZoneOptions, Intl.DateTimeFormat().resolvedOptions().timeZone),
9488
viewRef: RefControl<CommonPickerMethods>,
9589
...validationChildren,
9690
};
@@ -130,7 +124,7 @@ function validate(
130124

131125
const childrenMap = {
132126
value: stringExposingStateControl("value"),
133-
userTimeZone: stringExposingStateControl("userTimeZone" , 'Etc/UTC'),
127+
userTimeZone: stringExposingStateControl("userTimeZone", Intl.DateTimeFormat().resolvedOptions().timeZone),
134128
...commonChildren,
135129
...formDataChildren,
136130
};
@@ -275,7 +269,7 @@ export const timeRangeControl = (function () {
275269
const childrenMap = {
276270
start: stringExposingStateControl("start"),
277271
end: stringExposingStateControl("end"),
278-
userRangeTimeZone: stringExposingStateControl("userRangeTimeZone" , 'Etc/UTC'),
272+
userRangeTimeZone: stringExposingStateControl("userRangeTimeZone" , Intl.DateTimeFormat().resolvedOptions().timeZone),
279273
...formDataChildren,
280274
...commonChildren,
281275
};
@@ -420,38 +414,39 @@ export const timeRangeControl = (function () {
420414
.build();
421415
})();
422416

417+
const getTimeZoneInfo = (timeZone: any, othereTimeZone: any) => {
418+
const tz = timeZone === 'UserChoice' ? othereTimeZone : timeZone ;
419+
return {
420+
TimeZone: tz,
421+
Offset: dayjs().tz(tz).format('Z') // Get the UTC offset for the selected timezone
422+
};
423+
};
424+
423425
export const TimePickerComp = withExposingConfigs(timePickerControl, [
424426
new NameConfig("value", trans("export.timePickerValueDesc")),
425427

426428
depsConfig({
427429
name: "formattedValue",
428430
desc: trans("export.timePickerFormattedValueDesc"),
429-
depKeys: ["value", "format", "timeZone", "userTimeZone"],
431+
depKeys: ["value", "format", "timeZone", "userTimeZone"],
430432
func: (input) => {
431-
let mom = null;
432-
433-
// Loop through TimeParser to find a valid format
434-
for (const format of TimeParser) {
435-
if (dayjs.utc(input.value, format).isValid()) {
436-
mom = dayjs.utc(input.value, format);
437-
break;
438-
}
439-
}
440-
441-
const tz = input.timeZone === 'UserChoice' ? input.userTimeZone : input.timeZone || 'UTC';
442-
return mom?.isValid() ? mom.tz(tz).format(input.format) : '';
433+
const mom = Boolean(input.value) ? dayjs(input.value, TimeParser) : null;
434+
const tz = input.timeZone === 'UserChoice' ? input.userTimeZone : input.timeZone; // Get the selected timezone
435+
const timeInTz = mom?.clone().tz(tz, true); // Apply the selected timezone without altering the time itself (do not convert the time)
436+
const formattedTimeWithoffset = timeInTz?.format(input?.format);
437+
return mom?.isValid() ? (!input.format || input.format.includes('Z') || input.format.includes('z')) // Check if format is not available or contains 'Z'
438+
? formattedTimeWithoffset // Return formattedDateWithoffset if format includes 'Z' or is not available
439+
: mom.format(input.format) // Otherwise, return mom.format(input.format)
440+
: "";
443441
},
444442
}),
445443

446444
depsConfig({
447445
name: "timeZone",
448446
desc: trans("export.timeZoneDesc"),
449447
depKeys: ["timeZone", "userTimeZone"],
450-
func: (input) => {
451-
return input.timeZone === 'UserChoice' ? input.userTimeZone : input.timeZone || 'UTC';
452-
},
448+
func: (input: { timeZone: any; userTimeZone: any; }) => getTimeZoneInfo(input.timeZone, input.userTimeZone)
453449
}),
454-
455450
depsConfig({
456451
name: "invalid",
457452
desc: trans("export.invalidDesc"),
@@ -460,158 +455,87 @@ export const TimePickerComp = withExposingConfigs(timePickerControl, [
460455
validate({
461456
...input,
462457
value: { value: input.value },
463-
}).validateStatus !== "success",
458+
} as any).validateStatus !== "success",
464459
}),
465-
466460
...CommonNameConfig,
467461
]);
468462

469-
470463
export let TimeRangeComp = withExposingConfigs(timeRangeControl, [
471-
// new NameConfig("start", trans("export.timeRangeStartDesc")),
472-
// new NameConfig("end", trans("export.timeRangeEndDesc")),
473-
depsConfig({
474-
name: "start",
475-
desc: trans("export.timeRangeStartDesc"),
476-
depKeys: ["start", "timeZone", "userRangeTimeZone"],
477-
func: (input) => {
478-
let start = null;
479-
480-
// Loop through TimeParser to find a valid format for start
481-
for (const format of TimeParser) {
482-
if (dayjs.utc(input.start, format).isValid()) {
483-
start = dayjs.utc(input.start, format);
484-
break;
485-
}
486-
}
487-
488-
if (start?.hour() === 0 && start?.minute() === 0 && start?.second() === 0) {
489-
start = start?.hour(12);
490-
}
491-
492-
// Apply timezone conversion if valid
493-
const tz = input.timeZone === 'UserChoice' ? input.userRangeTimeZone : input.timeZone || 'UTC';
494-
return start?.isValid() ? start.tz(tz).format(input.format || "HH:mm:ss") : null;
495-
},
496-
}),
497-
498-
depsConfig({
499-
name: "end",
500-
desc: trans("export.timeRangeEndDesc"),
501-
depKeys: ["end", "timeZone", "userRangeTimeZone"],
502-
func: (input) => {
503-
let end = null;
504-
505-
// Loop through TimeParser to find a valid format for end
506-
for (const format of TimeParser) {
507-
if (dayjs.utc(input.end, format).isValid()) {
508-
end = dayjs.utc(input.end, format);
509-
break;
510-
}
511-
}
512-
513-
// Apply timezone conversion if valid
514-
const tz = input.timeZone === 'UserChoice' ? input.userRangeTimeZone : input.timeZone || 'UTC';
515-
return end?.isValid() ? end.tz(tz).format(input.format || "HH:mm:ss") : null;
516-
},
517-
}),
518-
464+
new NameConfig("start", trans("export.timeRangeStartDesc")),
465+
new NameConfig("end", trans("export.timeRangeEndDesc")),
519466
depsConfig({
520467
name: "formattedValue",
521468
desc: trans("export.timeRangeFormattedValueDesc"),
522469
depKeys: ["start", "end", "format", "timeZone", "userRangeTimeZone"],
523470
func: (input) => {
524-
let start = null;
525-
let end = null;
526-
for (const format of TimeParser) {
527-
if (dayjs.utc(input.start, format).isValid()) {
528-
start = dayjs.utc(input.start, format);
529-
break;
530-
}
531-
}
532-
for (const format of TimeParser) {
533-
if (dayjs.utc(input.end, format).isValid()) {
534-
end = dayjs.utc(input.end, format);
535-
break;
536-
}
537-
}
538-
539-
const tz = input.timeZone === 'UserChoice' ? input.userRangeTimeZone : input.timeZone || 'UTC';
540-
const formattedStart = start?.isValid() ? start.tz(tz).format(input.format) : '';
541-
const formattedEnd = end?.isValid() ? end.tz(tz).format(input.format) : '';
542-
543-
return [formattedStart, formattedEnd].filter(Boolean).join(" - ");
471+
const start = Boolean(input.start) ? dayjs(input.start, TimeParser) : null;
472+
const end = Boolean(input.end) ? dayjs(input.end, TimeParser) : null;
473+
const tz = input.timeZone === 'UserChoice' ? input.userRangeTimeZone : input.timeZone; // Get the selected timezone
474+
const startTimeInTz = start?.clone().tz(tz, true); // Apply the selected timezone without altering the time itself (do not convert the time)
475+
const endTimeInTz = end?.clone().tz(tz, true);
476+
return [
477+
start?.isValid() && (!input.format || input.format.includes('Z') || input.format.includes('z')) // Check if format is not available or contains 'Z'
478+
? startTimeInTz?.format(input?.format) // Return formattedTimeWithoffset if format includes 'Z' or is not available
479+
: start?.format(input.format),
480+
end?.isValid() && (!input.format || input.format.includes('Z') || input.format.includes('z'))
481+
? endTimeInTz?.format(input?.format)
482+
: end?.format(input.format) ,
483+
]
484+
.filter((item) => item)
485+
.join(" - ");
544486
},
545487
}),
546-
547488
depsConfig({
548489
name: "formattedStartValue",
549490
desc: trans("export.timeRangeFormattedStartValueDesc"),
550-
depKeys: ["start", "format", "timeZone", "userRangeTimeZone"],
491+
depKeys: ["start", "format" , "timeZone", "userRangeTimeZone"],
551492
func: (input) => {
552-
let start = null;
553-
for (const format of TimeParser) {
554-
if (dayjs.utc(input.start, format).isValid()) {
555-
start = dayjs.utc(input.start, format);
556-
break;
557-
}
558-
}
559-
560-
const tz = input.timeZone === 'UserChoice' ? input.userRangeTimeZone : input.timeZone || 'UTC';
561-
return start?.isValid() ? start.tz(tz).format(input.format) : '';
493+
const start = Boolean(input.start) ? dayjs(input.start, TimeParser) : null;
494+
const tz = input.timeZone === 'UserChoice' ? input.userRangeTimeZone : input.timeZone;
495+
const startTimeInTz = start?.clone().tz(tz, true);
496+
const formattedDate = startTimeInTz?.format(input?.format);
497+
return start?.isValid() && (!input.format || input.format.includes('Z') || input.format.includes('z'))
498+
? formattedDate
499+
: start?.format(input.format);
562500
},
563501
}),
564-
565502
depsConfig({
566503
name: "formattedEndValue",
567504
desc: trans("export.timeRangeFormattedEndValueDesc"),
568505
depKeys: ["end", "format", "timeZone", "userRangeTimeZone"],
569506
func: (input) => {
570-
let end = null;
571-
for (const format of TimeParser) {
572-
if (dayjs.utc(input.end, format).isValid()) {
573-
end = dayjs.utc(input.end, format);
574-
break;
575-
}
576-
}
577-
578-
const tz = input.timeZone === 'UserChoice' ? input.userRangeTimeZone : input.timeZone || 'UTC';
579-
return end?.isValid() ? end.tz(tz).format(input.format) : '';
507+
const end = Boolean(input.end) ? dayjs(input.end, TimeParser) : null;
508+
const tz = input.timeZone === 'UserChoice' ? input.userRangeTimeZone : input.timeZone;
509+
const endTimeInTz = end?.clone().tz(tz, true);
510+
return end?.isValid() && (!input.format || input.format.includes('Z') || input.format.includes('z'))
511+
? endTimeInTz?.format(input?.format)
512+
: end?.format(input.format);
580513
},
581514
}),
582-
583515
depsConfig({
584516
name: "timeZone",
585517
desc: trans("export.timeZoneDesc"),
586518
depKeys: ["timeZone", "userRangeTimeZone"],
587-
func: (input) => {
588-
return input.timeZone === 'UserChoice' ? input.userRangeTimeZone : input.timeZone || 'UTC';
589-
},
590-
}),
519+
func: (input:any) => getTimeZoneInfo(input.timeZone, input.userRangeTimeZone)
591520

521+
}),
592522
depsConfig({
593523
name: "invalid",
594524
desc: trans("export.invalidDesc"),
595525
depKeys: ["start", "end", "required", "minTime", "maxTime", "customRule"],
596-
func: (input) => {
597-
const startInvalid = validate({
526+
func: (input) =>
527+
validate({
598528
...input,
599529
value: { value: input.start },
600-
}).validateStatus !== "success";
601-
602-
const endInvalid = validate({
530+
}).validateStatus !== "success" ||
531+
validate({
603532
...input,
604533
value: { value: input.end },
605-
}).validateStatus !== "success";
606-
607-
return startInvalid || endInvalid;
608-
},
534+
}).validateStatus !== "success",
609535
}),
610-
611536
...CommonNameConfig,
612537
]);
613538

614-
615539
TimeRangeComp = withMethodExposing(TimeRangeComp, [
616540
...dateRefMethods,
617541
{
@@ -653,4 +577,4 @@ TimeRangeComp = withMethodExposing(TimeRangeComp, [
653577
comp.children.end.getView().onChange(data.end);
654578
},
655579
},
656-
]);
580+
]);

client/packages/lowcoder/src/comps/comps/dateComp/timeRangeUIView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const RangePickerStyled = styled((props: any) => <RangePicker {...props} />)<{ $
2121
`;
2222

2323
const StyledAntdSelect = styled(AntdSelect)`
24-
width: 100%;
24+
width: 300px;
2525
margin: 10px 0px;
2626
.ant-select-selector {
2727
font-size: 14px;
@@ -71,7 +71,7 @@ export const TimeRangeUIView = (props: TimeRangeUIViewProps) => {
7171
<StyledAntdSelect
7272
placeholder="Select Time Zone"
7373
options={timeZoneOptions.filter(option => option.value !== 'UserChoice')} // Filter out 'userChoice'
74-
defaultValue={'Etc/UTC'}
74+
defaultValue={Intl.DateTimeFormat().resolvedOptions().timeZone}
7575
onChange={props.handleTimeRangeZoneChange}
7676
/>
7777
)

client/packages/lowcoder/src/comps/comps/dateComp/timeUIView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const TimeMobileUIView = React.lazy(() =>
2121
);
2222

2323
const StyledAntdSelect = styled(AntdSelect)`
24-
width: 100%;
24+
width: 300px;
2525
margin: 10px 0;
2626
.ant-select-selector {
2727
font-size: 14px;
@@ -54,7 +54,7 @@ export const TimeUIView = (props: TimeUIViewProps) => {
5454
placeholder="Select Time Zone"
5555
options={timeZoneOptions.filter(option => option.value !== 'UserChoice')} // Filter out 'userChoice'
5656
onChange={props?.handleTimeZoneChange}
57-
defaultValue={'Etc/UTC'}
57+
defaultValue={Intl.DateTimeFormat().resolvedOptions().timeZone}
5858
/>
5959
)
6060
)}
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { trans } from "i18n";
22

33
export const timeZoneOptions = [
4-
{ label: trans("timeZone.UTC-12:00"), value: "Etc/GMT+12" },
5-
{ label: trans("timeZone.UTC-11:00"), value: "Etc/GMT+11" },
4+
{ label: trans("timeZone.UserChoice"), value: "UserChoice" },
5+
{ label: trans("timeZone.UTC-12:00"), value: "Pacific/Baker" },
6+
{ label: trans("timeZone.UTC-11:00"), value: "Pacific/Niue" },
67
{ label: trans("timeZone.UTC-10:00"), value: "Pacific/Honolulu" },
78
{ label: trans("timeZone.UTC-09:00"), value: "America/Anchorage" },
89
{ label: trans("timeZone.UTC-08:00"), value: "America/Tijuana" },
@@ -11,7 +12,7 @@ export const timeZoneOptions = [
1112
{ label: trans("timeZone.UTC-05:00"), value: "America/New_York" },
1213
{ label: trans("timeZone.UTC-04:00"), value: "America/Halifax" },
1314
{ label: trans("timeZone.UTC-03:00"), value: "America/Argentina/Buenos_Aires" },
14-
{ label: trans("timeZone.UTC-02:00"), value: "Etc/GMT+2" },
15+
{ label: trans("timeZone.UTC-02:00"), value: "Atlantic/South_Georgia" },
1516
{ label: trans("timeZone.UTC-01:00"), value: "Atlantic/Cape_Verde" },
1617
{ label: trans("timeZone.UTC+00:00"), value: "Etc/UTC" },
1718
{ label: trans("timeZone.UTC+01:00"), value: "Europe/Berlin" },
@@ -20,10 +21,15 @@ export const timeZoneOptions = [
2021
{ label: trans("timeZone.UTC+04:00"), value: "Asia/Dubai" },
2122
{ label: trans("timeZone.UTC+05:00"), value: "Asia/Karachi" },
2223
{ label: trans("timeZone.UTC+05:30"), value: "Asia/Kolkata" },
24+
{ label: trans("timeZone.UTC+05:45"), value: "Asia/Kathmandu" },
2325
{ label: trans("timeZone.UTC+06:00"), value: "Asia/Dhaka" },
26+
{ label: trans("timeZone.UTC+06:30"), value: "Asia/Rangoon" },
2427
{ label: trans("timeZone.UTC+07:00"), value: "Asia/Bangkok" },
2528
{ label: trans("timeZone.UTC+08:00"), value: "Asia/Shanghai" },
2629
{ label: trans("timeZone.UTC+09:00"), value: "Asia/Tokyo" },
30+
{ label: trans("timeZone.UTC+09:30"), value: "Australia/Darwin" },
2731
{ label: trans("timeZone.UTC+10:00"), value: "Australia/Sydney" },
28-
{ label: trans("timeZone.UserChoice"), value: "UserChoice" },
32+
{ label: trans("timeZone.UTC+11:00"), value: "Pacific/Guadalcanal" },
33+
{ label: trans("timeZone.UTC+12:00"), value: "Pacific/Auckland" },
34+
{ label: trans("timeZone.UTC+13:00"), value: "Pacific/Tongatapu" },
2935
];

0 commit comments

Comments
 (0)