<commit_before>/** @jsx createElement */

import _ from 'lodash'
import moment from 'moment'
import {createElement} from 'elliptical'

import { join, relativeDate, possibleDates } from './helpers'
import { DateTime, InternalDateTime } from './datetime'
import { Duration } from './duration'

const TrueDateTime = {
  describe ({props}) {
    return (
      <sequence>
        <literal text='all day ' id='allDay' value optional limited />

        <choice merge>
          <InternalDateTime {...props} id={undefined} />
          <map function={(result) => ({dateTime: result})}>
            <DateTime {...props} nullify />
          </map>
        </choice>
      </sequence>
    )
  }
}

function * mapRangeResults (result, props) {
  if (result.start && result.end) {
    if (!result.start.time && !result.end.time) {
      for (let startDate of possibleDates(result.start)) {
        for (let endDate of possibleDates(result.end)) {
          yield {
            start: join(startDate, {hour: 0, minute: 0, second: 0}, props.timezoneOffset),
            end: join(endDate, {hour: 0, minute: 0, second: 0}, props.timezoneOffset),
            allDay: true
          }
        }
      }
    } else {
      for (let startDate of possibleDates(result.start, result.end.date)) {
        for (let endDate of possibleDates(result.end, startDate)) {
          yield {
            start: join(startDate, result.start.time || props.defaultTime, props.timezoneOffset),
            end: join(endDate, result.end.time || props.defaultTime, props.timezoneOffset),
            allDay: false
          }
        }
      }
    }
  } else if (result.start && result.duration) {
    for (let startDate of possibleDates(result.start)) {
      const start = join(startDate, result.start.time || props.defaultTime, props.timezoneOffset)
      yield {
        start,
        end: moment(start).add(result.duration).toDate(),
        allDay: false
      }
    }
  } else if (result.start) {
    if (!result.start.time) {
      for (let startDate of possibleDates(result.start)) {
        yield {
          start: startDate,
          end: startDate,
          allDay: true
        }
      }
    } else {
      for (let startDate of possibleDates(result.start)) {
        const start = join(startDate, result.start.time, props.timezoneOffset)
        yield {
          start: start,
          end: moment(start).add(props.defaultDuration).toDate(),
          allDay: false
        }
      }
    }
  }
}

function * mapRangeOptions (option, props) {
  for (let result of mapRangeResults(option.result, props)) {
    yield _.assign({}, option, {result})
  }
}

function filterRangeOption (option) {
  if (option.result.allDay &&
      (!option.result.start._ambiguousTime ||
        (option.result.end && !option.result.end._ambiguousTime))) {
    return false
  }

  return true
}

export const Range = {
  defaultProps: {
    prepositions: false,
    seconds: true,
    defaultTime: {hour: 8},
    defaultDuration: {hours: 1},
    future: true,
    past: true,
    label: 'period of time'
  },
  
  filterResult (result, {props}) {
    const startMoment = moment(result.start)
    const endMoment = moment(result.end)

    if (endMoment.isBefore(startMoment)) return false

    const currentMoment = result.allDay ? moment({}) : moment()
    if (!props.past && currentMoment.isAfter(startMoment)) return false
    if (!props.future && currentMoment.isBefore(endMoment)) return false

    return true
  },


  describe ({props}) {
    return (
      <placeholder
        label={props.label}
        arguments={props.phraseArguments || (props.phraseArguments ? [props.phraseArgument] : [props.label])}>
        <map outbound={(option) => mapRangeOptions(option, props)} limit={1}>
          <filter outbound={filterRangeOption}>
            <sequence unique>
              <sequence id='duration' optional limited>
                {props.prepositions ? <literal text='for ' optional limited preferred /> : null}
                <Duration merge />
                <list items={[' ', ' starting ']} limit={1} />
              </sequence>

              <TrueDateTime ellipsis id='start' />

              <choice merge>
                <sequence id='end'>
                  <list items={[' to ', ' - ', '-']} limit={1} category='conjunction' /><commit_msg>Fix range filter for moment 2.14<commit_after>/** @jsx createElement */

import _ from 'lodash'
import moment from 'moment'
import {createElement} from 'elliptical'

import { join, relativeDate, possibleDates } from './helpers'
import { DateTime, InternalDateTime } from './datetime'
import { Duration } from './duration'

const TrueDateTime = {
  describe ({props}) {
    return (
      <sequence>
        <literal text='all day ' id='allDay' value optional limited />

        <choice merge>
          <InternalDateTime {...props} id={undefined} />
          <map function={(result) => ({dateTime: result})}>
            <DateTime {...props} nullify />
          </map>
        </choice>
      </sequence>
    )
  }
}

function * mapRangeResults (result, props) {
  if (result.start && result.end) {
    if (!result.start.time && !result.end.time) {
      for (let startDate of possibleDates(result.start)) {
        for (let endDate of possibleDates(result.end)) {
          yield {
            start: join(startDate, {hour: 0, minute: 0, second: 0}, props.timezoneOffset),
            end: join(endDate, {hour: 0, minute: 0, second: 0}, props.timezoneOffset),
            allDay: true
          }
        }
      }
    } else {
      for (let startDate of possibleDates(result.start, result.end.date)) {
        for (let endDate of possibleDates(result.end, startDate)) {
          yield {
            start: join(startDate, result.start.time || props.defaultTime, props.timezoneOffset),
            end: join(endDate, result.end.time || props.defaultTime, props.timezoneOffset),
            allDay: false
          }
        }
      }
    }
  } else if (result.start && result.duration) {
    for (let startDate of possibleDates(result.start)) {
      const start = join(startDate, result.start.time || props.defaultTime, props.timezoneOffset)
      yield {
        start,
        end: moment(start).add(result.duration).toDate(),
        allDay: false
      }
    }
  } else if (result.start) {
    if (!result.start.time) {
      for (let startDate of possibleDates(result.start)) {
        yield {
          start: startDate,
          end: startDate,
          allDay: true
        }
      }
    } else {
      for (let startDate of possibleDates(result.start)) {
        const start = join(startDate, result.start.time, props.timezoneOffset)
        yield {
          start: start,
          end: moment(start).add(props.defaultDuration).toDate(),
          allDay: false
        }
      }
    }
  }
}

function * mapRangeOptions (option, props) {
  for (let result of mapRangeResults(option.result, props)) {
    yield _.assign({}, option, {result})
  }
}

function filterRangeOption (option) {
  if (option.result.allDay &&
      (!option.result.start._ambiguousTime ||
        (option.result.end && !option.result.end._ambiguousTime))) {
    return false
  }

  return true
}

export const Range = {
  defaultProps: {
    prepositions: false,
    seconds: true,
    defaultTime: {hour: 8},
    defaultDuration: {hours: 1},
    future: true,
    past: true,
    label: 'period of time'
  },
  
  filterResult (result, {props}) {
    const startMoment = moment(result.start)
    const endMoment = moment(result.end)

    if (endMoment.isBefore(startMoment)) return false

    const currentMoment = result.allDay ? moment().startOf('day') : moment()
    if (!props.past && currentMoment.isAfter(startMoment)) return false
    if (!props.future && currentMoment.isBefore(endMoment)) return false

    return true
  },


  describe ({props}) {
    return (
      <placeholder
        label={props.label}
        arguments={props.phraseArguments || (props.phraseArguments ? [props.phraseArgument] : [props.label])}>
        <map outbound={(option) => mapRangeOptions(option, props)} limit={1}>
          <filter outbound={filterRangeOption}>
            <sequence unique>
              <sequence id='duration' optional limited>
                {props.prepositions ? <literal text='for ' optional limited preferred /> : null}
                <Duration merge />
                <list items={[' ', ' starting ']} limit={1} />
              </sequence>

              <TrueDateTime ellipsis id='start' />

              <choice merge>
                <sequence id='end'>
                  <list items={[' to ', ' - ', '-']} limit={1} category='conjunction' />
{'fraction_non_alphanumeric': 0.13322595490105846, 'fraction_numerical': 0.0028762080073630927, 'mean_word_length': 2.351195065535852, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2074396', 'n_tokens_mistral': 2544, 'n_tokens_neox': 2486, 'n_words': 617}