IOSの場合、ライブラリreact-native-community/datetimepicker
は、日時ピッカーを表示する日時モードをサポートしています。
ただし、このモードはAndroidでは使用できません。
日付用と時間用の2つの連続ピッカーを表示する回避策はありますか?
class ShiftTimingScreen extends Component {
state = {
dateTimePickerVisible: false,
dateOrTimeValue: new Date(),
};
render() {
return (
<View>
<TouchableOpacity
onPress={() => this.setState({ dateTimePickerVisible: true, })}
>
<Input
label='Shift Starts At'
placeholder={"01/01/2019 - 09:00 AM"}
editable={false}
value={this.state.dateOrTimeValue.toLocaleDateString()}
/>
</TouchableOpacity>
{this.state.dateTimePickerVisible &&
(<DateTimePicker
mode={"datetime"} // THIS DOES NOT WORK ON Android. IT DISPLAYS ONLY A DATE PICKER.
display='default' // Android Only
is24Hour={false} // Android Only
value={defaultShiftStartDateTime}
onChange={(event, value) => {
this.setState({
dateOrTimeValue: value,
dateTimePickerVisible: Platform.OS === 'ios' ? true : false,
});
if (event.type === "set")
console.log("value:" , value);
}}
/>)}
</View>
);
}
}
export default ShiftTimingScreen;
この制限の回避策を以下に示します。
import React, { Component } from 'react';
import { TouchableOpacity, View } from 'react-native';
import { Input } from 'react-native-elements';
import DateTimePicker from '@react-native-community/datetimepicker';
import XDate from 'xdate';
class ShiftTimingScreen extends Component {
state = {
// The values, which we get from each of the DateTimePickers.
// These values can be saved into your app's state.
StartingDateTimeValue: null,
ToDateValue: null,
ToTimeValue: null,
// for iOS & Android: When this flag is true, the relevant <DateTimePicker> is displayed
isStartingDateTimePickerVisible: false,
isToDatePickerVisible: false,
isToTimePickerVisible: false,
// The value of the <DateTimePicker> is stored in this variable, which is used to pass data between the date & time pickers
dateOrTimeValue: null,
// ONLY FOR Android: note that the current version of the <DateTimePicker> does NOT support "datetime" mode on Android.
// So, I am using the following 2 flags (datePickerVisible & timePickerVisible) to provide this functionality.
// (1) ONLY FOR Android: When the datePickerVisible flag is true, the <DateTimePicker> is displayed in "date" mode
datePickerVisible: false,
// (2) ONLY FOR Android: When the timePickerVisible flag is true, the <DateTimePicker> is displayed in "time" mode
timePickerVisible: false,
};
saveStartingDateTime = (value) => {
console.log("saveStartingDateTime - value:", value);
this.setState({
StartingDateTimeValue: value,
});
};
saveEndingDate = (value) => {
console.log("saveEndingDate - value:", value);
this.setState({
ToDateValue: value,
});
};
saveEndingTime = (value) => {
console.log("saveEndingTime - value:", value);
this.setState({
ToTimeValue: value,
});
};
fRenderDateTimePicker = (dateTimePickerVisible, visibilityVariableName, dateTimePickerMode, defaultValue, saveValueFunctionName ) => {
// dateTimePickerVisible: a flag, which is used to show/hide this DateTimePicker
// visibilityVariableName: the name of the state variable, which controls showing/hiding this DateTimePicker.
// The name of the variable is received in (visibilityVariableName), and the value of it is received in the argument (dateTimePickerVisible).
// dateTimePickerMode: the mode mode of this DateTimePicker
// defaultValue: the default value, which should be selected initially when the DatTimePicker is displayed
// saveValueFunctionName: the function, which would be called after the user selects a value.
// In my case it is a Redux's action creator, which saves the selected value in the app's state.
return (
<View>
{/* A. For iOS, display the picker in "date", "time" or "datetime" mode - No need for any customisation */}
{Platform.OS === 'ios' && dateTimePickerVisible &&
(<DateTimePicker
mode={dateTimePickerMode}
value={defaultValue}
onChange={ (event, value) => {
this.setState({
dateOrTimeValue: value,
// We are done. Hide the <DatTimePicker>
// Technically speaking, since this part of the script is only relevant to a certain platform, I don't need to check for the platform (below).
// Note that [visibilityVariableName] refers to the NAME of a state variable
[visibilityVariableName]: Platform.OS === 'ios' ? true : false,
});
if (event.type === "set") {
saveValueFunctionName(value);
// console.log("visibilityVariableName:", [visibilityVariableName], " - value:", value);
}
}}
/>)}
{/* B.1 For Android - "date" mode: display the picker in "date" mode */}
{/* For Android - "datetime" mode: display the picker in "date" mode (to be followed by another picker (below) in "time" mode) */}
{Platform.OS === 'Android' && dateTimePickerVisible && this.state.datePickerVisible &&
(<DateTimePicker
mode={"date"}
display='default' // 'default', 'spinner', 'calendar', 'clock' // Android Only
value={defaultValue}
onChange={ (event, value) => {
this.setState({
// In case of (mode == datetime), the TIME part will be added to "dateOrTimeValue" using another DateTimePicker (below).
dateOrTimeValue: value,
datePickerVisible: false,
});
// When the mode is "datetime" & this picker was set (the user clicked on OK, rather than cancel),
// we need to display another DateTimePicker in TIME mode (below)
if (event.type === "set" && dateTimePickerMode === "datetime") {
this.setState({
timePickerVisible: true,
});
}
// When the mode is "date" & this picker was set (the user clicked on OK, rather than cancel),
// (1) We need to hide this picker.
// (2) Save the data. Otherwise, do nothing. Date will be saved after the TIME picker is launched (below).
else if (event.type === "set" && dateTimePickerMode === "date") {
// console.log("saveValueFunctionName: ", saveValueFunctionName);
this.setState({
[visibilityVariableName]: Platform.OS === 'ios' ? true : false,
});
saveValueFunctionName(value);
// console.log("visibilityVariableName:", [visibilityVariableName], " - value:", value);
}
}}
/>)}
{/* B.2 For Android - "time" mode: display the picker in "time" mode */}
{/* For Android - "datetime" mode: display the picker in "time" mode (following another picker (above) in "date" mode) */}
{Platform.OS === 'Android' && dateTimePickerVisible && this.state.timePickerVisible &&
(<DateTimePicker
mode={"time"}
display='spinner' // 'default', 'spinner', 'calendar', 'clock' // Android Only
is24Hour={false} // Android Only
value={defaultValue}
onChange={(event, value) => {
// 1. In case of (mode == "time"), (value) is assigned to (newDateTime), which will be used below (as is with no additions)
let newDateTime = value;
// 2. In case of (mode == "datetime"),
if (event.type === "set" && dateTimePickerMode === "datetime") {
// 2.1. Get the (date) part from the previously displayed DATE picker, which saved its value into (this.state.dateValue)
newDateTime = this.state.dateOrTimeValue;
// 2.2. Get the (hours & minutes) parts from this TIME Picker, which saved its value into (value)
const newHours = value.getHours();
const newMinutes = value.getMinutes();
// 2.3 Combine 2.1 & 2.2 (above) into (newDateTime).
newDateTime.setHours(newHours);
newDateTime.setMinutes(newMinutes);
newDateTime.setSeconds(0);
}
this.setState({
dateOrTimeValue: newDateTime,
datePickerVisible: false,
timePickerVisible: false,
// We are done. Hide the <DatTimePicker>
// Technically speaking, since this part of the script is only relevant to a certain platform, I don't need to check for the platform (below).
[visibilityVariableName]: Platform.OS === 'ios' ? true : false,
});
if (event.type === "set") {
saveValueFunctionName(newDateTime);
// console.log("visibilityVariableName:", [visibilityVariableName], " - newDateTime:", newDateTime);
}
}}
/>)}
</View>
);
};
// This function formats date values. Obviously, using it is optional.
// If you decide to use it, remember that it needs the XDate library:
// import XDate from 'xdate';
fFormatDateTime = (date1, format1 = "datetime") => {
// date1: the date to be formatted
// format1: the date mode - "datetime" , "date" OR "time"
if (date1 === null) {
return null;
}
// else:
const format2 = format1.toLowerCase();
let dateFormatted;
const date2 = new XDate(date1);
switch (format2) {
case "datetime": {
dateFormatted = date2.toString('dd/MM/yyyy - hh:mm TT');
return dateFormatted;
}
case "date": {
dateFormatted = date2.toString('dd/MM/yyyy');
return dateFormatted;
}
case "time": {
dateFormatted = date2.toString('hh:mm TT');
return dateFormatted;
}
default:
return null;
}
};
// This function shows/hides the initial DateTimePicker
// If the mode is "datetime", another picker will be displayed by the DATE picker
fRenderDatePicker = (mode, visibilityVariableName) => {
// mode: specifies the mode of the <DateTimePicker>
// visibilityVariableName: the name of the state variable, which controls showing/hiding this DateTimePicker.
switch (mode) {
case "datetime":
return this.setState({ [visibilityVariableName]: true, datePickerVisible: true, timePickerVisible: false });
case "date":
return this.setState({ [visibilityVariableName]: true, datePickerVisible: true, timePickerVisible: false });
case "time":
return this.setState({ [visibilityVariableName]: true, datePickerVisible: false, timePickerVisible: true });
}
}
render() {
// 1. For the "Shift Start", Initial/Default value for the DateTimePicker
// // defaultShiftStartDateTime: (tomorrow's date at 9 AM)
let defaultShiftStartDateTime = new Date();
defaultShiftStartDateTime.setDate(defaultShiftStartDateTime.getDate() + 1);
defaultShiftStartDateTime.setHours(9);
defaultShiftStartDateTime.setMinutes(0);
defaultShiftStartDateTime.setSeconds(0);
// 2. For the "Shift End", Initial/Default value for the DateTimePicker
let defaultShiftEndDateTime = new Date();
defaultShiftEndDateTime.setDate(defaultShiftEndDateTime.getDate() + 1);
defaultShiftEndDateTime.setHours(17);
defaultShiftEndDateTime.setMinutes(0);
defaultShiftEndDateTime.setSeconds(0);
return (
<View>
<TouchableOpacity
// THE FOLLOWING ARGUMENT VALUE IS THE (1st place OF 2) PLACES, WHICH DIFFERENTIATE BETWEEN THE DIFFERENT MODES (DATETIME, DATE & TIME)
onPress={() => {
// this.setState({ isStartingDateTimePickerVisible: true, });
this.fRenderDatePicker("datetime", "isStartingDateTimePickerVisible");
}}>
<Input
label='Starting Date & Time'
placeholder={"01/01/2019 - 09:00 AM"}
editable={false}
value={this.fFormatDateTime(this.state.StartingDateTimeValue)}
/>
</TouchableOpacity>
{// This function would render the necessary DateTimePicker only if the relevant state variable is set (above)
this.fRenderDateTimePicker(
this.state.isStartingDateTimePickerVisible,
"isStartingDateTimePickerVisible",
// THE FOLLOWING ARGUMENT VALUE IS THE (2nd place OF 2) PLACES, WHICH DIFFERENTIATE BETWEEN THE DIFFERENT MODES (DATETIME, DATE & TIME)
"datetime",
defaultShiftStartDateTime,
// This is my function, which saves the selected value to my app's state.
// YOU NEED TO REPLACE IT WITH SOMETHING RELEVANT TO YOUR APP.
this.saveStartingDateTime,
)}
<TouchableOpacity
onPress={() => {
// this.setState({ isToDatePickerVisible: true, });
this.fRenderDatePicker("date", "isToDatePickerVisible");
}}>
<Input
label='Ending Date'
placeholder={"01/01/2019"}
editable={false}
value={this.fFormatDateTime(this.state.ToDateValue, "date")}
/>
</TouchableOpacity>
{this.fRenderDateTimePicker(
this.state.isToDatePickerVisible,
"isToDatePickerVisible",
"date",
defaultShiftEndDateTime,
// This is my function, which saves the selected value to my app's state.
// YOU NEED TO REPLACE IT WITH SOMETHING RELEVANT TO YOUR APP.
this.saveEndingDate,
)}
<TouchableOpacity
onPress={() => {
// this.setState({ isToTimePickerVisible: true, });
this.fRenderDatePicker("time", "isToTimePickerVisible");
}}>
<Input
label='Ending Time'
placeholder={"09:00 AM"}
editable={false}
value={this.fFormatDateTime(this.state.ToTimeValue, "time")}
/>
</TouchableOpacity>
{this.fRenderDateTimePicker(
this.state.isToTimePickerVisible,
"isToTimePickerVisible",
"time",
defaultShiftEndDateTime,
// This is my function, which saves the selected value to my app's state.
// YOU NEED TO REPLACE IT WITH SOMETHING RELEVANT TO YOUR APP.
this.saveEndingTime,
)}
</View>
);
} // end of: render()
} // end of: component
export default ShiftTimingScreen;
以下のコードを使用して、react-native-community/datetimepicker
パッケージを使用して日付と時刻を選択しました。お役に立てば幸いです。
const [date, setDate] = useState(
props.item.time ? new Date(props.item.time) : new Date() // to set default from props or current date
);
const [time, setTime] = useState(
props.item.time ? new Date(props.item.time) : new Date() // to set default from props or current date
);
const [mode, setMode] = useState('date');
const [show, setShow] = useState(false);
const onChange = (event, selectedValue) => {
setShow(Platform.OS === 'ios');
if (mode == 'date') {
const currentDate = selectedValue || new Date();
setDate(currentDate);
setMode('time');
setShow(Platform.OS !== 'ios'); // to show time
} else {
const selectedTime = selectedValue || new Date();
setTime(selectedTime);
setShow(Platform.OS === 'ios'); // to hide back the picker
setMode('date'); // defaulting to date for next open
}
};
const showMode = currentMode => {
setShow(true);
setMode(currentMode);
};
const showDatePicker = () => {
showMode('date');
};
return
(<View>
<TouchableOpacity onPress={showDatePicker}>
<Text style={styles.title}>{formatDate(date, time)}</Text>
</TouchableOpacity>
{show && (
<DateTimePicker
value={date}
minimumDate={Date.parse(new Date())}
display='default'
mode={mode}
onChange={onChange}
/>
)}
</View>);
const formatDate = (date, time) => {
return `${date.getDate()}/${date.getMonth() +
1}/${date.getFullYear()} ${time.getHours()}:${time.getMinutes()}`;
};