I'd like to create a custom time zone converter, any pointers?

30 views Asked by At

In my database I have a data set with date (startdatetime) and zone (timezone). Zone is posted into the DB from a different application that uses C# DateObject.

Ex. (UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague OR another example (UTC-10:00) Hawaii

I need to create a component that can convert date (startdatetime) and zone (timezone) to the users choosing, so I created a dropdown that uses time zones from moment-timezone library. UNFORTUNATELY it doesn't convert (or accurately if it does) the C# DateObject format since it's not in the same format as moment-timezone.

So I either have to create a dictionary where for example it converts '(UTC-08:00) Pacific Time (US & Canada)' to 'America/Los_Angeles|PST PDT|80 70|0101|1Lzm0 1zb0 Op0' or create my own custom dynamic timezone converter. Which I have tried but I keep getting incorrect time.

I could be missing something in moment-timezone docs (since I am new to the library) but as of now this is my existing code (before I was informed that the timezone will be on C# Date Object format and not on moment-timezone format).

import React, {useState, useEffect} from 'react';
import CloseIcon from '@material-ui/icons/Close';
import { makeStyles } from '@material-ui/core/styles';
import { useSelector, useDispatch } from "react-redux";
import {setRunListData, getRunDataAllGroupedAsync, setIsAllRunListDataShown, setTimeZone} from "../actions/index";
import * as Utils from '../../utils/utils';
import { Select, MenuItem, FormControl } from '@mui/material';
import moment from 'moment-timezone';
import {
    Typography,
    IconButton,
    Button,
    Dialog,
    DialogTitle, 
    DialogActions
  } from '@material-ui/core';

const TimeZone = (props) => {
    const { handleClose, isOpen } = props;
    
    const runlist = useSelector(state => state.runlist);
    const jwt = useSelector(state => state.jwt);
    const is_all_run_list_data_shown = useSelector(state => state.is_all_run_list_data_shown);
    const dispatch = useDispatch();

    const [selectedTimeZone, setSelectedTimeZone] = React.useState(localStorage.getItem('time_zone') || 'PST8PDT');
    const [originalRunlist, setOriginalRunlist] = useState(runlist);
    const zones = Utils.zones;

    useEffect(() => {
        setOriginalRunlist(is_all_run_list_data_shown);
    }, [is_all_run_list_data_shown])


    const useStyles = makeStyles((theme) => ({
        dialogWrapper: {
            padding: theme.spacing(2),
            position: 'absolute',
            top: theme.spacing(2),
        },
        dialogTitle: {
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
        },
        closeIcon: {
            marginLeft: 'auto',
        },
        storagesContainer: {
            display: 'flex',
            justifyContent: 'space-evenly', 
            gap: 5, 
            margin: '20px 0px',
        },
        alertContainer: {
            display: 'flex',
            alignItems: 'center',
            marginLeft: '20px 0px',
            overflow: 'hidden',
          },
        inputContainer: {
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'space-evenly',
            margin: '15px 0px',
            //overflow: 'hidden',
        },
        outlineInput: {
            height: 20,
            width: 50,
            marginLeft: 10,
            marginRight: 10,
        },
        buttonContainer: {
            display: 'flex',
            justifyContent: 'space-evenly',
            overflow: 'hidden',
        },
        defaultButton: {
            margin: theme.spacing(1),
            background: 'linear-gradient(113.96deg, #E9F5F5 100%, #D9E7F4 100%)',
            border: '0.5px solid #CCCCCC',
            boxSizing: 'border-box',
            borderRadius: '4px',
            color: '#189AB4',
            width: 150,
            '&:disabled': {
                background: '#f0f0f0', // Change this to the desired disabled background color
                color: '#666666', // Change this to the desired disabled text color
            },
        },
        button: {
            margin: theme.spacing(1),
            background: '-webkit-gradient(linear, left top, right bottom, from(#0075a9), to(#003049))',
            border: '0.5px solid #CCCCCC',
            boxSizing: 'border-box',
            borderRadius: '4px',
            color: 'white',
            width: 150,
            '&:disabled': {
                background: '#f0f0f0', // Change this to the desired disabled background color
                color: '#666666', // Change this to the desired disabled text color
            },
        },
        formControl: {
            "& .MuiInputBase-root": {
              borderWidth: "1px",
              borderStyle: "solid",
              minWidth: "120px",
              width: "280px",
              justifyContent: "center",
              cursor: "pointer" // Set cursor to pointer
            },
            "& .MuiSelect-select.MuiSelect-select": {
              paddingRight: "15px"
            },
            marginLeft: "auto" // Move the FormControl to the right
          },
    }));

    const classes = useStyles();

    const handleChange = (event) => {
        setSelectedTimeZone(event.target.value);
    };

    const handleDefaultRunlistDate = () => {
        setSelectedTimeZone('PST8PDT');
        dispatch(setTimeZone('PST8PDT'));
        originalRunlist ? dispatch(getRunDataAllGroupedAsync(undefined, jwt)) : dispatch(getRunDataAllGroupedAsync(100, jwt));
    }

    function toTimeZone(time, zone) {
        try {
            var format = 'MM/DD/YYYY HH:mm:ss';
            return moment(time, format).tz(zone).format(format);
        } catch (error) {
            console.log(error)
        }
    }

    const handleUpdateRunlistDate = () => {
        let copyRunList = structuredClone(runlist);
        const updatedRunlist = copyRunList.map(entry => {
            if(entry.timezone){
                const startDatetime = toTimeZone(entry.startdatetime, selectedTimeZone);
                entry.startdatetime = startDatetime;
                entry.timezone = selectedTimeZone;
            }
            return entry;
        });
        dispatch(setTimeZone(selectedTimeZone));
        dispatch(setRunListData(updatedRunlist));
    }

    return (
        <>
        <Dialog disableEnforceFocus onClose={handleClose} aria-labelledby="customized-dialog-title" open={isOpen} fullWidth maxWidth={'sm'} classes={{paper: classes.dialogWrapper}}>
            <DialogTitle>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                    <Typography variant="h6">Time Zone Settings</Typography>
                    <IconButton onClick={handleClose}>
                        <CloseIcon />
                    </IconButton>
                </div>
            </DialogTitle>
            <div className={classes.inputContainer}>
                    <Typography>Time Zone Name:</Typography>
                    <FormControl className={classes.formControl}>
                        <Select
                            labelId="zone-label"
                            id="zone-select"
                            value={selectedTimeZone}
                            onChange={handleChange}
                        >
                            {zones.map((zone, index) => (
                            <MenuItem key={index} value={zone.split('|')[0]}>
                                {zone.split('|')[0]}
                            </MenuItem>
                            ))}
                        </Select>
                    </FormControl>
            </div>
            <div className={classes.buttonContainer}>
                <DialogActions>
                <Button autoFocus color="primary" className={classes.defaultButton} onClick={handleDefaultRunlistDate}>
                    Default
                </Button>
                <Button autoFocus color="primary" className={classes.button} onClick={handleUpdateRunlistDate}>
                    Apply
                </Button>
                </DialogActions>
            </div>
        </Dialog>
        </>
    );

}

export default TimeZone;

Any tips?

0

There are 0 answers