everyone has a crazy cousin eddie
12 stories

Flatware for germophobes

5 Comments and 9 Shares


Dawoochen makes a line of flatware, called Head Up, for people who don't want the business end of their forks, knives, and spoons from touching the microbes teeming on the dinner table.

The Dawoochen Head up flat ware set is an innovative and hygienic product designed to keep the part that goes into your mouth free from touching the surface and this can perfectly prevent various bacteria and dust on the dining tablet from getting into the mouth through table ware.

Read the whole story
2090 days ago
Holiday gift option for a handful of friends...
Geneva, Switzerland
2091 days ago
Want, if only because I have a beagle and her hair is *everywhere*. So if a fork touches the table, 4 white+brown hairs are immediately attached.
Cambridge, Massachusetts
Share this story
3 public comments
2088 days ago
Nobody just rests the head of the utensil on their plate? Have I been breaking some etiquette rule?
Bend, Oregon
2088 days ago
I've just been putting the fork in my jacket pocket between bites
2088 days ago
2091 days ago
Not for home, but very yes for restaurants.

Wednesday assorted link

1 Comment

1. John Key.

Read the whole story
2658 days ago
others have come forward as targets of his hair-pulling.
Geneva, Switzerland
Share this story

Little date commands redux

1 Comment

Back in December, I wrote a short utility called ago, which calculated the number of days between a date given on the command line and today. It’s been useful, but too often I’ve found myself giving it input in the wrong format. Rather than retrain myself to match ago’s expectations, I rewrote ago to match mine.

As originally written, ago wanted two or three arguments: the month, day, and (optionally) year of the date. These were to be given as space-separated numbers, e.g.

ago 8 30 14

to get the number of days since August 30, 2014, or

ago 2 5

to get the number of days since February 5 of this year. The problem was the spaces. My natural inclination in writing a date is to use slashes or dashes between the numbers, e.g.

ago 8/30/14


ago 2-5

Using spaces was the lazy way out. Because Unix automatically parses arguments based on space separation, I didn’t have to write a date parser in ago. But after a few months of use, I realized that the time I saved by not including a parser was eaten up by the time I spent rerunning ago after giving it the wrong input.

And I didn’t even have to write a date parser. Although the Python standard library doesn’t include the kind of forgiving parser that would allow both slashes and dashes as separators, the well-established dateutil library by Gustavo Niemeyer does. It also allows dot separators and text, like feb 5. Using it even shortened ago’s code. And the best news is that even though dateutil isn’t in the standard library, it is included by default in OS X.

Here’s the new version of ago:

 1:  #!/usr/bin/env python
 3:  from datetime import datetime
 4:  from dateutil.parser import parse
 5:  import sys
 7:  # The date is given on the command line in American format.
 8:  then = parse(sys.argv[1], dayfirst=False, yearfirst=False)
 9:  now = datetime.today()
11:  ago = now - then
13:  if sys.argv[0].split('/')[-1] == 'til':
14:    print -ago.days
15:  else:
16:    print ago.days

The parse function in Line 8 returns a datetime object, as does the today function in Line 9. The subtraction in Line 11 returns a timedelta object, from which we return the days attribute in Line 14 or 16.

Because the ago code can also count days until a future date, I made a hard link to ago called til.

ln ago til

The logic of Lines 13–16 flips the sign of the result so I don’t get negative numbers if I use til to inquire about a date in the future. Instead of using

ago 12/25

and getting -284 as the result, I can use

til 12/25

and get 284. Not a big deal, but a cute little affordance.1

I should mention that the rules parse uses for two-digit years are a little different from what I used in the original version of ago. From the dateutil documentation:

When a two digit year is found, it is processed considering the current year, so that the computed year is never more than 49 years after then current year, nor 50 years before the current year. In other words, if we are in year 2003, and the year 30 is found, it will be considered as 2030, but if the year 60 is found, it will be considered 1960.

Now that it’s 2015, a year of 60 is considered 2060, not 1960.

With a rewritten ago under my belt, I decided to write a similar little utility that I’ve sometimes wished for: a quick way to get the difference in days between two dates. I call this script between. It’s used as you might expect:

between 8/23/1960 5/27

to get the number of days between August 23, 1960 and May 27 of this year. This is, as I mentioned in the post back in December, the day I become 20,000 days old. Jiminy.

The source code for between is

 1:  #!/usr/bin/env python
 3:  from dateutil.parser import parse
 4:  import sys
 6:  # The dates are given on the command line in American format.
 7:  day1 = parse(sys.argv[1], dayfirst=False, yearfirst=False)
 8:  day2 = parse(sys.argv[2], dayfirst=False, yearfirst=False)
10:  between = day2 - day1
11:  print between.days

There’s nothing in between that isn’t already in ago. I could, I suppose, modify between to act like ago when only one argument is given, but I think of the commands as distinctly different, so I don’t mind the redundancy.

If the second argument is earlier than the first, between will return a negative number. I could’ve added some logic to always return a positive number, but I didn’t see any value in that.

Back when Perl was my main language, I used its Date::Manip module for all kinds of date parsing and arithmetic. It was a huge module, and its load time was detectable—there was always a delay after issuing a command that used Date::Manip. But it was a remarkably full-featured library, and its parser was far more flexible and forgiving than dateutil’s. But dateutil is plenty good for what I need in these scripts and it doesn’t hesitate before giving me the answer.

  1. The link can’t be called until because that’s the name of a bash command for looping. 

[If the formatting looks odd in your feed reader, visit the original article]

Read the whole story
2702 days ago
Geneva, Switzerland
Share this story

Adam Engst on BBEdit 11

1 Comment

Adam Engst:

Bare Bones Software has released BBEdit 11, a notable upgrade to the venerable text editor that, I’m extremely pleased to say, requires an upgrade fee. Why would I be happy about the opportunity for current users to spend money? Because it reinforces the fact that we are Bare Bones’ customers. We’re the ones that Rich Siegel and company are trying to please.

It’s remarkable that an app I first started using in 1992 on System 7 is still going strong today.

Read the whole story
2840 days ago
Geneva, Switzerland
2840 days ago
2839 days ago
Are you saying you were using emacs on a Mac in 1992 as well?
Share this story

RFC for a better C calendaring library

1 Comment

In the process of working on my Time, Clock, and Calendar Programming In C document, I have learned something sad but important: the standard Unix calendar API is irremediably broken.

The document list a lot of consequences of the breakage, but here I want to zero in on what I think is the primary causes. That is: the standard struct tm (a) fails to be an unambiguous representation of time, and (b) violates the SPOT (Single Point of Truth) design rule. It has some other more historically contingent problems as well, but these problems (and especially (a)) are the core of its numerous failure modes.

These problems cannot be solved in a backwards-compatible way. I think it’s time for a clean-sheet redesign. In the remainder of this post I’ll develop what I think the premises of the design ought to be, and some consequences.

The functions we are talking about here are tzset(), localtime(3), gmtime(3), mktime(3), strftime(3), and strptime() – everything (ignoring some obsolete entry points) that takes a struct tm argument and/or has timezone issues.

The central problem with this group of functions is the fact that the standard struct tm (what manual pages hilariously call “broken-down-time”) was designed to hold a local time/date without an offset from UTC time. The consequences of this omission cascade through the entire API in unfortunate ways.

Here are the standard members:

struct tm 
    int    tm_sec;   /* seconds [0,60] (60 for + leap second) */
    int    tm_min;   /* minutes [0,59] */
    int    tm_hour;  /* hour [0,23] */
    int    tm_mday;  /* day of month [1,31] */
    int    tm_mon ;  /* month of year [0,11] */
    int    tm_year;  /* years since 1900 */
    int    tm_wday;  /* day of week [0,6] (Sunday = 0) */
    int    tm_yday;  /* day of year [0,365] */
    int    tm_isdst; /* daylight saving flag */

The presence of the day of year and day of week members violates SPOT. This leads to some strange behaviors – mktime(3) “normalizes” its input structure by fixing up these members. This can produce subtle gotchas.

Also, note that there is no way to represent dates with subsecond precision in this structure. Therefore strftime(3) cannot format them and strptime(3) cannot parse them.

The GNU C library takes a swing at the most serious problem by adding a GMT offset member, but only half-heartedly. Because it is concerned with maintaining backward compatibility, that member is underused.

Here’s what I think it ought to look like instead

struct gregorian 
    float  sec;     /* seconds [0,60] (60 for + leap second) */
    int    min;     /* minutes [0,59] */
    int    hour;    /* hour [0,23] */
    int    mday;    /* day of month [1,31] */
    int    mon;     /* month of year [1,12] */
    int    year;    /* years Gregorian */
    int    zoffset; /* zone offset, seconds east of Greenwich */
    char   *zone;   /* zone name or NULL */
    int    dst;     /* daylight saving offset, seconds */

Some of you, I know, are looking at the float seconds member and bridling. What about roundoff errors? What about comparisons? Here’s where I introduce another basic premise of the redesign: integral floats are safe to play with..

That wasn’t true when the Unix calendar API was designed, but IEEE754 solved the problem. Most modern FPUs are well-behaved on integral quantities. There is not in fact a fuzziness risk if you stick to integral seconds values.

The other way to handle this – the classic Unix way – would have been to add a decimal subseconds member in some unit, probably nanoseconds in 2014. The problem with this is that it’s not future-proof. Who’s to say we won’t want finer resolution in a century?

Yes, this does means decimal subsecond times will have round-off issues when you do certain kinds of arithmetic on them. I think this is tolerable in calendar dates, where subsecond arithmetic is unusual thing to do to them.

The above structure fixes some quirks and inconsistencies, The silly 1900 offset for years is gone. Time divisions of a day or larger are consistently 1-origin as humans expect; this will reduce problems when writing and reading debug messages. SPOT is restored for the calendar portion of dates.

The zoffset/zone/dst group do not have the SPOT property – zone can be inconsistent with the other two members. This is, alas, unavoidable if we’re going to have a zone member at all, which is pretty much a requirement in order for the analogs of strftime(3) and strptime() to have good behavior.

Now I need to revisit another basic assumption of the Unix time API: that the basic time type is integral seconds since the epoch. In the HOWTO I pointed out that this assumption made sense in a world of 32-bit registers and expensive floating point, but no longer in a world of 64-bit machines and cheap floating point.

So here’s the other basic decision: the time scalar for this library is quad-precision seconds since the epoch in IEEE74 (that is, 112 52 bits of mantissa).

Now we can begin to sketch some function calls. Here are the basic two:

struct gregorian *unix_to_gregorian(double time, struct gregorian *date, char *zone)

Float seconds since epoch to broken-down time. A NULL zone argument means UTC, not local time. This is important because we want to be able to build a version of this code that doesn’t do lookups through the IANA zone database for embedded applications.

double gregorian_to_unix(struct gregorian *date)

Broken-down time to float seconds. No zone argument because it’s contained in the structure. Actually this function wouldn’t use the zone member but just the zoffset member; this is significant because we want to limit lookups to the timezone database for performance reasons.

struct gregorian *gregorian_to_local(struct gregorian *date, char *zone)

Broken-down time to broken-down time normalized for the specified zone. In this case a null zone just means normalize so there are no out-of-range structure elements (e.g. day 32 wraps to the 1st, 2nd, or 3rd of the next month) without applying any zone change. (Again, this is so the IANA timezone database is not a hard dependency).

Notice that both functions are re-entrant and can take constant arguments.

An auxiliary function we’ll need is:

char *local_timezone(void)

so we can say this:

unix_to_gregorian(time, datebuffer, local_timezone())

We only need two other functions: gregorian_strf() and gregorian_strp(), patterned after strftime() and strptime(). These present no great difficulties. Various strange bugs and glitches in the existing functions would disappear because zone offset and name are part of the structures they operate on.

Am I missing anything here? This seems like it would be a large improvement and not very difficult to write.

Read the whole story
2868 days ago
talk to the astronomers who both write code AND work to define UT0. they will have both insight and experience on the matter.
Geneva, Switzerland
Share this story

New Release

1 Comment

The Taskwarrior team would like to announce the simultaneous release of Taskwarrior 2.3.0 and Taskserver 1.0.0.

Taskwarrior 2.3.0

Taskserver 1.0.0

We would like to thank everyone for the questions, complaints, bugs, feature requests, code patches, doc patches, test platforms, ideas, arguments, discussions, persistence and patience.

We especially want to thank those who donated continuous integration build server time.

Read the whole story
3124 days ago

congratulations to the team on a big step forward. taskserver will open up many new possibilities for users (and parallel development)
Geneva, Switzerland
Share this story
Next Page of Stories