question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Supporting marking on a range of dates by simply pass a start and an end date #1286

See original GitHub issue

https://github.com/wix/react-native-calendars/issues/1286#issue-694098729

Description

Is there a way which allows me to simply pass the start date and the end date of a date range as the props, so the entire date range will automatically be marked on the calendar? So far I have to implement it by working out a list containing all the dates in this range, and pass them as an bulky object with attributes like selected and color for each single date. I read through the read.me file and I assume this is the only offical documentation? I’d like to know if there’s a better way to implement this. Otherwise I’ll make a suggestion about this feature. Thanks.

Expected Behavior

Click a start date, click an end date, all dates in this range will be selected. Like that: image I got it from another package.

Observed Behavior

Only exact dates in an object passed to markedDates will be marked. If there’re 20 days, I have to pass 20 different dates in.

If there’s an error message, please paste the full terminal output and error message in this code block:

N/A

Environment

N/A

Reproducible Demo

N/A

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:6
  • Comments:6

github_iconTop GitHub Comments

9reactions
williamanjocommented, Jun 3, 2021

@nguyenvantruong17 I found the following code

 import React, { setState, useState, useEffect } from 'react';
 import { Calendar, CalendarList, Agenda } from 'react-native-calendars';
 import { LocaleConfig } from 'react-native-calendars';
 import { MaterialIcons } from '@expo/vector-icons';
 import _isEmpty from 'lodash/isEmpty'
 import moment from 'moment';

 export default class CalendarWithPeriodFill extends React.Component {
     state = {
       start: {},
       end: {}, 
       period: {},
  }


 getDateString(timestamp) {
    const date = new Date(timestamp)
    const year = date.getFullYear()
    const month = date.getMonth() + 1
    const day = date.getDate() 

 let dateString = `${year}-`
 if (month < 10) {
   dateString += `0${month}-`
 } else {
   dateString += `${month}-`
 }
 if (day < 10) {
   dateString += `0${day}`
 } else {
   dateString += day
 }

return dateString
}

getPeriod(startTimestamp, endTimestamp) {
  const periodo = {}
  let currentTimestamp = startTimestamp
  while (currentTimestamp < endTimestamp) {
    const dateString = this.getDateString(currentTimestamp)
    periodo[dateString] = {
      color: '#58e8f5',
      startingDay: currentTimestamp === startTimestamp,
    }
    currentTimestamp += 24 * 60 * 60 * 1000
  }
  const dateString = this.getDateString(endTimestamp)
  periodo[dateString] = {
    color: '#4ed2de',
    endingDay: true,
  }
  return periodo
}

setDay(dayObj) {
  const { start, end } = this.state
  const {
    dateString, day, month, year,
  } = dayObj
  // timestamp returned by dayObj is in 12:00AM UTC 0, want local 12:00AM
  const timestamp = new Date(year, month - 1, day).getTime()
  const newDayObj = { ...dayObj, timestamp }
  // if there is no start day, add start. or if there is already a end and start date, restart
  const startIsEmpty = _isEmpty(start)
  if (startIsEmpty || !startIsEmpty && !_isEmpty(end)) {
    const periodo = {
      [dateString]: {
        color: '#4ed2de',
        endingDay: true,
        startingDay: true,
      },
    }
    this.setState({ start: newDayObj, period : periodo, end: {} })
  } else {
    // if end date is older than start date switch
    const { timestamp: savedTimestamp } = start
    if (savedTimestamp > timestamp) {
      const periodo = this.getPeriod(timestamp, savedTimestamp)
      this.setState({ start: newDayObj, end: start, period: periodo })
    } else {
      const periodo = this.getPeriod(savedTimestamp, timestamp)
      this.setState({ end: newDayObj, start : start, period : periodo })
    }
  }
}

render() {
  const { period } = this.state
  return (
    <Calendar
      onDayPress={this.setDay.bind(this)}
      current={moment().format('YYYY-MM-DD')}
      minDate={'2001-01-01'}
      maxDate={'2030-12-31'}
      onDayLongPress={(day) => {
        console.log('selected day', day.dateString);
      }}
     monthFormat={'MMMM - yyyy'}
      onMonthChange={(month) => {
        console.log('month changed', month);
     }}
     hideArrows={false}
     renderArrow={(direction) =>
      direction == 'left' ? (
        <MaterialIcons name="arrow-back" size={24} color="#3485E4" />
      ) : (
        <MaterialIcons name="arrow-forward" size={24} color="#3485E4" />
      )
    }
     hideExtraDays={true}
     firstDay={1}
     onPressArrowLeft={(subtractMonth) => subtractMonth()}
     onPressArrowRight={(addMonth) => addMonth()}
     disableAllTouchEventsForDisabledDays={true}
     enableSwipeMonths={true}
     markingType={'period'}
     markedDates={period}
     />
   )
 }
}
4reactions
mawais78commented, Feb 14, 2022

I wrote this code for functional components.

import {
  StyleSheet, Text, View
} from 'react-native'
import { connect } from 'react-redux'
import { Calendar } from "react-native-calendars";
import moment from "moment";

const CalendarView = props => {
  const [startDay, setStartDay] = useState(null);
  const [endDay, setEndDay] = useState(null);
  const [markedDates, setMarkedDates] = useState({});

  return(
    <View style={styles.row}>
      <Calendar
        style={{
          marginTop: 40
        }}
        onDayPress={(day) => {
          if (startDay && !endDay) {
            const date = {}
            for (const d = moment(startDay); d.isSameOrBefore(day.dateString); d.add(1, 'days')) {
              date[d.format('YYYY-MM-DD')] = {
                marked: true,
                color: 'black',
                textColor: 'white'
              };

              if(d.format('YYYY-MM-DD') === startDay) date[d.format('YYYY-MM-DD')].startingDay = true;
              if(d.format('YYYY-MM-DD') === day.dateString) date[d.format('YYYY-MM-DD')].endingDay = true;
            }

            setMarkedDates(date);
            setEndDay(day.dateString);
          } else {
            setStartDay(day.dateString)
            setEndDay(null)
            setMarkedDates({
              [day.dateString]: {
                marked: true,
                color: 'black',
                textColor: 'white',
                startingDay: true,
                endingDay: true
              }
            })
          }
        }}
        monthFormat={"yyyy MMM"}
        hideDayNames={false}
        markingType={'period'}
        markedDates={markedDates}
        theme={{
          selectedDayBackgroundColor: '#646464',
          selectedDayTextColor: 'white',
          monthTextColor: 'blue',
          dayTextColor: 'black',
          textMonthFontSize: 18,
          textDayHeaderFontSize: 16,
          arrowColor: '#e6e6e6',
          dotColor: 'black'
        }}
      />
    </View>
  );
}

const mapStateToProps = state => {
  return {
  }
}

export default connect(mapStateToProps, {
  
})(CalendarView)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Supporting marking on a range of dates by simply pass a start ...
Click a start date, click an end date, all dates in this range will be selected. Observed Behavior. Only exact dates in an...
Read more >
Iterating through a range of dates in Python - Stack Overflow
Maybe the most elegant solution is using a generator function to completely hide/abstract the iteration over the range of dates: from datetime import...
Read more >
Examples of using dates as criteria in Access queries
Contain a date within the last 7 days. Between Date() and Date()-6. Returns items with dates during the last 7 days. If today's...
Read more >
Excel SUMIFS date range formula - sum if between two dates
How to sum if between two dates in Excel. To sum values within a certain date range, use a SUMIFS formula with start...
Read more >
wix - Bountysource
Supporting marking on a range of dates by simply pass a start and an end date #1286 $ 0. Created 1 year ago...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found