I was reading a question on stackoverflow recently and I became a little curious/interested in the philosophy behind Ramda (functional programming for Javascript). So I thought I would try an exercise.

I chose to write some code to parse and format ISO8601 date strings, and try to use those with the Date object. This is something that I am fairly familiar with in the usual Javascript style.

This is what I have so far, after a day of reading and experimenting.

var C = {};
C.negFour = R.always(-4);
C.negTwo = R.always(-2);
C.negOne = R.always(-1);
C.zero = R.always(0);
C.one = R.always(1);
C.two = R.always(2);
C.four = R.always(4);
C.minus = R.always('-');
C.empty = R.always('');

var L = {};
L.toNumbers = R.map(Number);
L.toStrings = R.map(String);
L.ofZeros = R.repeat(C.zero());
L.joinMinus = R.join(C.minus());
L.joinEmpty = R.join(C.empty());

var N = {};
N.add1 = R.add(R.__, C.one());
N.subtract1 = R.subtract(R.__, C.one());

var S = {};
S.splitMinus = R.split(C.minus());
S.ofZeros = R.compose(L.joinEmpty, L.ofZeros);
S.prependZeros = R.useWith(R.concat, [R.lift(S.ofZeros)(R.identity), R.identity]);
S.sliceLast = R.slice(R.__, Infinity);
S.sliceLast2 = S.sliceLast(C.negTwo());
S.sliceLast4 = S.sliceLast(C.negFour());
S.padStartZero1 = R.compose(S.sliceLast2, S.prependZeros(C.one()));
S.padStartZero4 = R.compose(S.sliceLast4, S.prependZeros(C.four()));

var D = {};
D.adjustJSMonth = R.adjust(N.subtract1, C.one());
D.adjustGregorianMonth = R.adjust(N.add1, C.one());
D.parseISODateToArgs = R.compose(D.adjustJSMonth, L.toNumbers, S.splitMinus);
D.yearLens = R.lensIndex(C.zero());
D.monthLens = R.lensIndex(C.one());
D.dayLens = R.lensIndex(C.two());
D.getYearArg = R.view(D.yearLens);
D.getISOYear = R.compose(S.padStartZero4, D.getYearArg);
D.getMonthArg = R.view(D.monthLens);
D.getISOMonth = R.compose(S.padStartZero1, D.getMonthArg);
D.getDayArg = R.view(D.dayLens);
D.getISODay = R.compose(S.padStartZero1, D.getDayArg);
D.setYearArg = R.set(D.yearLens);
D.setMonthArg = R.set(D.monthLens);
D.setDayArg = R.set(D.dayLens);
D.setISOYear = R.lift(D.setYearArg)(R.lift(D.getISOYear)(R.identity), R.identity);
D.setISOMonth = R.lift(D.setMonthArg)(R.lift(D.getISOMonth)(R.identity), R.identity);
D.setISODay = R.lift(D.setDayArg)(R.lift(D.getISODay)(R.identity), R.identity);
D.argsToISO = R.compose(D.setISOYear, D.setISOMonth, D.setISODay);
D.argsToISOString = R.compose(L.joinMinus, D.argsToISO, D.adjustGregorianMonth);
D.parse = R.useWith(R.apply(Date.UTC), [R.lift(D.parseISODateToArgs)(R.identity)]);
D.date = function(dateString) {
  return new Date(D.parse(dateString));
D.toArgs = function(d) {
  return [d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()];
D.toISODateString = R.lift(D.argsToISOString)(D.toArgs);
D.msInDay = R.always(86400000);
D.daysToMs = R.multiply(D.msInDay());
D.day = function(date, dow) {
  date.setTime(R.add(date.getTime(), D.daysToMs(R.subtract(dow, date.getDay()))));
  return date;
D.getPreviousSaturday = R.compose(D.toISODateString, R.lift(D.day)(R.identity, C.negOne), D.date);

var previousSaturday = D.getPreviousSaturday('2016-09-17');
<script src="//cdn.jsdelivr.net/ramda/latest/ramda.min.js"></script>

The code is working, and to me looks quite like the code I have seen in examples. But I'd really like to check that I am going in the correct direction with what I have done, it has been difficult to prevent myself coding in the usual style.

I'd like to know what improvements I could make, I still have some code which is written as functions which I don't know if it is even possible to translate. Some of the code seems, and probably is, unnecessary. It would be really great to get some feedback to further my knowledge on the subject.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.