How to get AM/PM from TimePickerAndroid in React Native - react-native

I'm using TimePickerAndroid of React Native and using 12hours timing,
So, it is working fine and shows AM/PM to select and picker returned me hours and minutes, but I did not found anyway to get that AM is selected or PM, code is below.
async showTimePicker() {
const { action, minute, hour } = await TimePickerAndroid.open({
is24Hour: false,
});
if (action === TimePickerAndroid.dismissedAction) {
return;
}
const selectedTime = `${hour}:${minute}`;
this.setState({ selectedTime })
}
I just need to know that AM is selected or PM everything else is working fine.
official docs for reference.
Thank you.

Flag is just for showing to the user inside the timer popup. Once user selects the time, It will give you 24 hour format only.. If user select "2:00 PM", the return value will be 14 hours and 00 minutes. while displaying in any other place, You can just convert into AM/PM and display it.
Expect only 24 hours format from the TimePickerAndroid.

You can use a condition to display AM/PM, here I added an example code segment for you. Sriraman's answer also explained to use this kind of method.
async showTimePicker() {
var { action, minute, hour } = await TimePickerAndroid.open({
is24Hour: false,
});
if (action === TimePickerAndroid.dismissedAction) {
return;
}
// setting AM/PM and hour to 12 by checking condition
let am_pm = 'AM';
if(hour>11){
am_pm = 'PM';
if(hour>12){
hour = hour - 12;
}
}
if(hour == 0){
hour = 12;
}
const selectedTime = `${hour}:${minute} ${am_pm}` ;
this.setState({ selectedTime })
}

Whatever bool value you set for is24Hour, the time picker returns hours in the 24 hour format. That is, if you select 8:00 PM, the time picker returns the JSON Object {action:'timeSetAction', hour:20, minute:0}.
You're right that the official docs doesn't show this.

Related

Moment JS seemingly returning random date

Moment JS is returning a random date.
I am trying to create a calendar in a react-native project. I created this loop to count back the days from today's date. I have attached my console and tried to clearly show how I tried to debug this.
The subtract method seems not to recognise the loop and the i value seems to stay at 16.
Any help would be greatly appreciated.
This is the code that is causing all the fussThis is the output in the console
Per Moment.js, moments are mutable. Clone the moment before performing date math
https://momentjs.com/guides/#/lib-concepts/mutability/
You'll need to create a new moment instance or clone the existing one when performing operations like .add(), .subtract(), etc.
const moment = require("moment");
const today = moment();
// count back N days
const N = 3;
let i = 1;
let days = [];
// #1 - Create a new moment instance from today and add -i days
while (i <= N) {
const day = moment(today).add(-i, "days");
days.push(day);
i++;
}
console.log("Approach #1");
console.log({ days });
// #2 - A moment is mutable. So we use add() to mutate today by -1 days each iteration, clone the instance, and push to array
i = 0;
days = [];
while (i < N) {
const day = today.add(-1, "days").clone();
days.push(day);
i++;
}
console.log("Approach #2");
console.log({ days });

FullCalendar V4 - How to account for shorter months in a recurring event series?

I'm using FullCalendar v4-alpha-3 with the RRule plugin to generate recurring events. It works as expected with only one problem: how do I modify a recurring event to account for months with fewer days than the starting month in a series?
For example, if the first monthly occurrence happens on January 29, 2019; the event will be repeated on the 29th of all subsequent months except in February since it only has 28 days (leap years excluded).
I've tried resetting dtstart to the first day of the following month. It works, except the event is no longer recursive.
Here's a stripped down snippet of my setup:
let calendar = new Calendar(calendarEl, {
plugins: [ rrulePlugin ],
events: [
{
rrule: 'DTSTART:20190129 RRULE:FREQ=MONTHLY;UNTIL=20200130;COUNT=13;BYMONTHDAY=29'
}
],
eventRender: function(info) {
...
// reset start date to the first day of the following month
// if current month has fewer days than base month
let start = event.start;
let day = start.getDate();
let now = new Date();
let currentMonth = now.getMonth();
let currentYear = now.getFullYear();
let daysInCurrent = getDaysInMonth(currentMonth + 1, currentYear);
let nextStart = start;
if (day > daysInCurrent) {
nextStart = new Date(currentYear, currentMonth + 1, 1);
event.setStart(nextStart);
event.setEnd(null);
}
}
});
I'd appreciate any insight.
Not quite the solution I hoped for, but RRule's bysetpos property seems to offer the next best alternative as it allows for a fallback date in case the one specified doesn't exist.
For example, the following would generate an occurrence on the 30th of every month; or the last day of the month if the 30th doesn’t exist:
FREQ=MONTHLY;BYMONTHDAY=28,29,30;BYSETPOS=-1.
Sourced from: https://icalevents.com/2555-paydays-last-working-days-and-why-bysetpos-is-useful/
I know this is an old question but maybe this will be usefull for someone:
I'm using momentjs library
monthly:
let endofmonth = moment('2020-02-29', "YYYY-MM-DD").endOf('month').format('DD');
let curday = moment('2020-02-29, "YYYY-MM-DD").format('DD');
single_event.title = title;
single_event.rrule = {};
single_event.rrule.freq = 'monthly';
single_event.rrule.dtstart = start_date;
single_event.rrule.interval = reminder_interval;
single_event.rrule.count = reminder_count;
if(endofmonth == curday){
// Checking if given day of the month is last
single_event.rrule.byweekday = ['mo','tu','we','th','fr','sa','su'];
single_event.rrule.bysetpos = -1;
}
else{
single_event.rrule.bymonthday = parseInt(curday);
}
calendar_events.push(single_event);
var calendar = new FullCalendar.Calendar(calendarEl, {
...
events: calendar_events
});
yearly:
single_event.title = title;
single_event.rrule = {};
single_event.rrule.dtstart = start_date;
single_event.rrule.count = parseInt(reminder_count);
if(endofmonth == curday){
// Checking if given day of the month is last
single_event.rrule.freq = 'monthly'; // Will work as yearly if interval is 12
single_event.rrule.interval = parseInt(reminder_interval)*12;
single_event.rrule.bymonthday = [28,29,30,31];
single_event.rrule.bysetpos = -1;
}
else{
single_event.rrule.freq = 'yearly';
single_event.rrule.bymonthday = parseInt(curday);
}
calendar_events.push(single_event);
var calendar = new FullCalendar.Calendar(calendarEl, {
...
events: calendar_events
});

Express Validatior - How Do I Break The Validation Chain?

I have a date field that I want to ensure is in a valid format and if so is the user over 18. The format is YYYY-MM-DD.
Here is one of my validators - the one that is failing:
body('birthday', 'Date format should be: YYYY-MM-DD')
.isRFC3339()
.custom(date => {
const over18 = moment().diff(date, 'years') >= 18;
if(!over18) {
return Promise.reject('You must be 18 or over!');
}
}),
Currently what happens is if the date is not a RFC3339 date the validation chain continues. This is problematic because moment produces an error if I pass an ill formatted date.
How do I break the chain after the call to .isRFC3339() so that if the date is invalid the custom validator will not run? I couldn't find anything in the docs
You can use momentjs strict mode together with String + Format parsing using moment.ISO_8601 (or moment.HTML5_FMT.DATE) special formats.
Your code could be like the following:
body('birthday', 'Date format should be: YYYY-MM-DD')
// .isRFC3339() // no more needed
.custom(date => {
const mDate = moment(date, moment.ISO_8601, true);
const over18 = moment().diff(mDate, 'years') >= 18;
if(!mDate.isValid()) {
return Promise.reject('Date is not YYYY-MM-DD');
if(!over18) {
return Promise.reject('You must be 18 or over!');
}
}),

Luxon - set milliseconds for toISO()

I'm using the following to get the end of day for a date coming from a date picker:
var date = DateTime.fromISO('2018-05-05').endOf('day');
What I want to end up with is
"2018-05-05T23:59:59+02:00"
however, I cannot get rid of the milliseconds:
console.log(date.toISO({suppressMilliseconds: true}));
// => outputs "2018-05-05T23:59:59.999+02:00"
Is there a more elegant way to do this besides simply setting the millisecond to 0:
date.c.millisecond = 0;
console.log(date.toISO({suppressMilliseconds: true}));
// => outputs "2018-05-05T23:59:59+02:00"
Right, suppressMilliseconds only applies if they're 0. (See here).
But there's a much easier way to round down the second:
DateTime.fromISO('2018-05-05')
.endOf('day')
.startOf('second')
.toISO({ suppressMilliseconds: true })
You should never mutate the Luxon object like in your workaround.
const { DateTime } = require("luxon");
let time = DateTime.now().set({milliseconds: 0});
time = time.toISO({suppressMilliseconds: true});
console.log(time);
It should help and solve the problem.
The way I did :
DateTime.now().toISO().replace(/\.\d{0,3}/, "");
Using RegExp to remove the "." and millis
I was having
2021-02-22T18:03:29.519Z
With the replace RegExp
2021-02-22T18:05:44Z

How to prevent user to enter specific times in datetimepicker?

I am using angular-bootstrap-datetimepicker. I know how to restrict the user from entering specific dates.
$dates.filter(function(date){
return (date.localDateValue() <= new Date().valueOf()-(24*60*60*1000));
}).forEach(function(date){
date.selectable = false;
})
This code insode startDateBefore render, prevents user from entering dates 24h past the current date.
But now I want users to enter spectic times only. Like user can select only times between 10:05am to 11:10pm. I am unable to do that. Documentation doesn't specify on how to add filter to hour and minutes. Any help on that.
In Angular Date Time Picker, the beforeRender function also takes parameter called view. So we can use the view==='hour' to restrict users from entering past hours. I was missing the code for hours.
function startDateBeforeRender ($view, $dates, $leftDate, $upDate, $rightDate) {
var today = moment().valueOf();
$dates.filter(function (date) {
return date.localDateValue() < today -(24*60*60*1000)
}).forEach(function (date) {
date.selectable = false;
});
// to restrict hours by admin
if ($view === "hour") {
// restict previous hours
$dates.filter(function (date) {
return date.localDateValue() < today
}).forEach(function (date) {
date.selectable = false;
})
}
}
date = new Date().valueOf();
if( date > 1000*(10*60+5) ){
if( date < 1000*(23*60+10) ){
//Code green, I repeat, CODE GREEN!
}
}