Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moment.js alternatives (date-fns) #816

Closed
amkoehler opened this issue Apr 20, 2018 · 18 comments
Closed

Moment.js alternatives (date-fns) #816

amkoehler opened this issue Apr 20, 2018 · 18 comments

Comments

@amkoehler
Copy link
Contributor

Do you want to request a feature or report a bug?

Feature

This library supports Moment.js and Globalize.js for localization. I was wondering if you had any plans to add other localization libraries, specifically date-fns. Moment is a very powerful library, but it does not offer the same bundle size optimizations as date-fns. There's a great discussion on the differences here. The main benefits of date-fns over Moment are performance and a more optimized bundle.

If this isn't really on your radar, no worries. I may still make an attempt at a PR if that's the case.

@arecvlohe
Copy link
Collaborator

@amkoehler I think it's a good idea to allow other alternatives like date-fns. I like date-fns as well and use it with this library outside of the initial setup with moment. It will be nice to see a PR on this if you get around to it!

@dmitrykrylov
Copy link
Contributor

dmitrykrylov commented May 31, 2018

@amkoehler @arecvlohe I tried to implement RBC localizer for date-fns v1.29.0. I've found the next issues:

  1. RBC's localizers require parse function with possibility to provide locale argument. Date-fns v1 doesn't support parsing with localization. It seems that it will be added in v2.
  2. startOfWeek function from date-fns v1 doesn't take locale parameter (it can take weekStartsOn value but not an actual locale object). date-fns v2-alpha already has this feature. A possible workaround for v1 is to hardcode mapping between locales and weekStartsOn number.

Therefore probably it's better to wait for date-fns v2. Let's help date-fns community to update locales for v2: https://github.com/date-fns/date-fns/blob/master/outdatedLocales.json

@GavinThomas1192
Copy link

I would also really like to see support for different packages. I need to use luxon, which is going to be moment's predecessor. Moment.js is taboo here because of optimization..

@jquense
Copy link
Owner

jquense commented Jun 13, 2018

We aren't likely to support a lot of options out of box, but the API is pluggable specifically so folks can use whatever they want @GavinThomas1192 can you give a Luxon localizer a shot and if there are api failings please report back.

@GavinThomas1192
Copy link

Yes, this will be my priority tomorrow! I’ve spent about a week implementing a super custom react big calendar and would really like to be able to use all of my work. So this is a high priority. My company absolutely won’t allow me to use moment

@ltegman
Copy link

ltegman commented Jun 18, 2018

Inspired by some conversation in #118, Here's a first swag at a luxon localizer. Hasn't been tested enough for me to call it bulletproof, but it seems to work so far in a quick smoke test.

import { set } from 'react-big-calendar/lib/formats'
import { set as setLocalizer } from 'react-big-calendar/lib/localizer'
import dates from 'react-big-calendar/lib/utils/dates'

const dateRangeFormat = ({ start, end }, culture, local) =>
  `${local.format(start, 'D', culture)}${local.format(end, 'D', culture)}`

const timeRangeFormat = ({ start, end }, culture, local) =>
  `${local.format(start, 't', culture)}${local.format(end, 't', culture)}`

const timeRangeStartFormat = ({ start }, culture, local) =>
  `${local.format(start, 't', culture)} — `

const timeRangeEndFormat = ({ end }, culture, local) => ` — ${local.format(end, 't', culture)}`

const weekRangeFormat = ({ start, end }, culture, local) =>
  `${local.format(start, 'MMMM dd', culture)} - ${local.format(
    end,
    dates.eq(start, end, 'month') ? 'dd' : 'MMMM dd',
    culture
  )}`

export const formats = {
  dateFormat: 'dd',
  dayFormat: 'dd EEE',
  weekdayFormat: 'ccc',

  selectRangeFormat: timeRangeFormat,
  eventTimeRangeFormat: timeRangeFormat,
  eventTimeRangeStartFormat: timeRangeStartFormat,
  eventTimeRangeEndFormat: timeRangeEndFormat,

  timeGutterFormat: 't',

  monthHeaderFormat: 'MMMM yyyy',
  dayHeaderFormat: 'dddd MMM dd',
  dayRangeHeaderFormat: weekRangeFormat,
  agendaHeaderFormat: dateRangeFormat,

  agendaDateFormat: 'EEE MMM dd',
  agendaTimeFormat: 't',
  agendaTimeRangeFormat: timeRangeFormat,
}

export default function(DateTime, { firstDayOfWeek }) {
  const locale = (d, c) => (c ? d.reconfigure(c) : d)

  set(formats)

  return setLocalizer({
    firstOfWeek() {
      return firstDayOfWeek
    },

    parse(value, format, culture) {
      return locale(DateTime.fromFormat(value, format), culture).toJSDate()
    },

    format(value, format, culture) {
      return locale(DateTime.fromJSDate(value), culture).toFormat(format)
    },
  })
}
LuxonLocalizer(DateTime, { firstDayOfWeek: 0 })

@adueck
Copy link

adueck commented Oct 16, 2018

Thank you @ltegman, really hoping this works well. I really would love to be able to display a calendar based on a set time zone, and not the time zone of the client's browser. (ie. issue #118)

Could you please provide a bit more detail about how exactly you use this with react-big-calendar?

Right now I am using moment like this:

import moment from 'moment';
import BigCalendar from 'react-big-calendar';
import 'react-big-calendar/lib/css/react-big-calendar.css';
const localizer = BigCalendar.momentLocalizer(moment);

then on my calendar component:

<BigCalendar 
    localizer={localizer}
    events={this.state.events}
    startAccessor="start"
    endAccessor="end"
/>

How exactly would I import the code and attach the LuxonLocalizer as per your example above?

Thanks for the help if possible. 🙇

@steph4nc
Copy link

steph4nc commented Nov 2, 2018

@adueck I'm also interested in date-fns support. There is a pull request you can look at, they are waiting for date-fns v2 to come out of alpha before they merge it, but it has been in alpha for so long, they can just as well add it. #855

@adueck
Copy link

adueck commented Nov 6, 2018

@steph4nc Not sure how clean this, but I actually made a work around that works great for me. I am adjusting the date/times in all the events based on the offset from the the timezone in the client's browser.

function calculateTimeDifference() {
  const testDate = new Date();
  const timezoneOffset = testDate.getTimezoneOffset();
  const calendarTimeOffset = -120; // THE TIMEZONE OFFSET FROM THE TIMEZONE YOU WANT THE CALENDAR TO DISPLAY IN
  return (timezoneOffset - calendarTimeOffset) / 60;
}

const timeDifference = calculateTimeDifference();
this.setState({ timeDifference: timeDifference });
// Adjust all the events in state according to the client's difference in time from desired calendar time
this.setState(prevState => {
    const adjusted = prevState.events;
    adjusted.forEach(event => {
        event.start = new Date(event.start.setHours(event.start.getHours() + timeDifference));
        event.end = new Date(event.end.setHours(event.end.getHours() + timeDifference));
    });
    return { events: adjusted };
});

This can also be applied to the clicking and dragging creation of events, to adjust their times accordingly

handleSelect({start, end}) {
  const title = window.prompt('New Event name');
  if (title) {
    // Add event to db (compensating for users timezone offset)
    const eventToSubmit = {
      title: title,
      start: new Date(start.setHours(start.getHours() - this.state.timeDifference)),
      end: new Date(end.setHours(end.getHours() - this.state.timeDifference))
    };
    fetch(`${apiUrl}events`,
    {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(eventToSubmit),
        credentials: "include"
    }).then((res) => res.json())
    .then((res) => {
      // Add event to state - with id for event returned from db
      const _id = res._id
      const adjustedStart = new Date(start.setHours(start.getHours() + this.state.timeDifference));
      const adjustedEnd = new Date(end.setHours(end.getHours() + this.state.timeDifference));
      this.setState({ events: [...this.state.events,
        {
          start,
          end,
          title,
          _id
        },],});
    });
  }
}

@ghost
Copy link

ghost commented Feb 19, 2019

Can't personally vouch for it but have read about Day.Js as an alternative

⏰ Day.js 2KB immutable date library alternative to Moment.js with the same modern API

https://github.com/iamkun/dayjs

reference: moment/moment#2373 (comment)

@TrySound
Copy link
Collaborator

@xxyuk We are planning to migrate to https://github.com/dmtrKovalenko/date-io as interop layer which supports day.js and date-fns.

@nshoes
Copy link

nshoes commented Mar 20, 2019

@TrySound do you have a timeline on that?

@TrySound
Copy link
Collaborator

Not yet. Would you like to help?

@nshoes
Copy link

nshoes commented Mar 20, 2019

I do have a day week our company donates to open source :) How big of a project is it?

@mmlumba
Copy link

mmlumba commented Mar 26, 2019

Are there plans to support Luxon for localization?

@stale
Copy link

stale bot commented May 25, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@dctalbot
Copy link

dctalbot commented Jan 24, 2020

PR for Luxon localizer is RFR here: #1574
Can't say whether it will be merged or not, but wanted to point this conversation to it.

@AceLondon
Copy link

AceLondon commented Jun 3, 2020

@jquense I don't know what your availability is but I would love to see this PR reviewed and released! (just a nudge to help get it over the finish line)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.