Esempio n. 1
0
def strftimeEx(fmt, t, timetuple=None):
    """
    Extends time.strftime() to format milliseconds and microseconds.

    Expects input to be a floating-point number of seconds since epoch.
    The additional formats are:

    - ``%(ms)``:  milliseconds (uses round())
    - ``%(ms_)``: milliseconds (uses floor())
    - ``%(us)``:  microseconds (uses round())

    The format may also be a callable which will bypass time.strftime() entirely.
    """
    if callable(fmt):
        return fmt(t)

    if "%(ms)" in fmt:
        # Assume that fmt does not also contain %(ms_) and %(us).
        # (It really doesn't make sense to mix %(ms) with those.)
        secs, frac = divmod(round(t,3), 1)
        ms = int(round(1e3*frac))
        fmt = fmt.replace("%(ms)", "%03d" % ms)
    else:
        # Assume fmt contains %(ms_) and %(us).
        secs, frac = divmod(round(t,6), 1)
        ms = int(round(1e3*frac))
        ms_, us = divmod(int(round(1e6*frac)),1000)
        fmt = fmt.replace("%(ms_)", "%03d" % ms_)
        fmt = fmt.replace("%(us)", "%03d" % us)

    if not timetuple:
        timetuple = localtime(secs)

    return strftime(fmt, timetuple)
Esempio n. 2
0
    def format(self, ticks, numlabels=None, char_width=None, fill_ratio = 0.3,
               ticker=None):
        """ Formats a set of time values.

        Parameters
        ----------
        ticks : array of numbers
            The tick values to be formatted
        numlabels
            Not used.
        char_width : number
            The total character width available for labelling the interval.
        fill_ratio : 0.0 < float <= 1.0
            Ratio of the available width that will be occupied by label text.
        ticker : AbstractScale object
            Object that can calculate the number of labels needed.

        Returns
        -------
        List of formatted labels.

        """
        # In order to pick the right set of labels, we need to determine
        # the resolution of the ticks.  We can do this using a ticker if
        # it's provided, or by computing the resolution from the actual
        # ticks we've been given.
        if len(ticks) == 0:
            return []

        span = abs(ticks[-1] - ticks[0])
        if ticker:
            r = ticker.resolution
        else:
            r = span / (len(ticks) - 1)
        resol = self._get_resolution(r, span)

        widths, formats = self.formats[resol]
        format = formats[0]
        if char_width:
            # If a width is provided, then we pick the most appropriate scale,
            # otherwise just use the widest format
            good_formats = array(formats)[widths * len(ticks) < fill_ratio * char_width]
            if len(good_formats) > 0:
                format = good_formats[-1]

        # Apply the format to the tick values
        labels = []
        resol_ndx = self.format_order.index(resol)

        # This dictionary maps the name of a time resolution (in self.format_order)
        # to its index in a time.localtime() timetuple.  The default is to map
        # everything to index 0, which is year.  This is not ideal; it might cause
        # a problem with the tick at midnight, january 1st, 0 a.d. being incorrectly
        # promoted at certain tick resolutions.
        time_tuple_ndx_for_resol = dict.fromkeys(self.format_order, 0)
        time_tuple_ndx_for_resol.update( {
                "seconds" : 5,
                "minsec" : 4,
                "minutes" : 4,
                "hourmin" : 3,
                "hours" : 3,
                })

        # As we format each tick, check to see if we are at a boundary of the
        # next higher unit of time.  If so, replace the current format with one
        # from that resolution.  This is not the best heuristic in the world,
        # but it works!  There is some trickiness here due to having to deal
        # with hybrid formats in a reasonable manner.
        for t in ticks:
            try:
                tm = localtime(t)
                s = strftimeEx(format, t, tm)
            except ValueError, e:
                warnings.warn("Unable to convert tick for timestamp " + str(t))
                labels.append("ERR")
                continue

            hybrid_handled = False
            next_ndx = resol_ndx

            # The way to check that we are at the boundary of the next unit of
            # time is by checking that we have 0 units of the resolution, i.e.
            # we are at zero minutes, so display hours, or we are at zero seconds,
            # so display minutes (and if that is zero as well, then display hours).
            while tm[ time_tuple_ndx_for_resol[self.format_order[next_ndx]] ] == 0:
                next_ndx += 1
                if next_ndx == len(self.format_order):
                    break
                if resol in ("minsec", "hourmin") and not hybrid_handled:
                    if (resol == "minsec" and tm.tm_min == 0 and tm.tm_sec != 0) or \
                        (resol == "hourmin" and tm.tm_hour == 0 and tm.tm_min != 0):
                        next_format = self.formats[self.format_order[resol_ndx-1]][1][0]
                        s = strftimeEx(next_format, t, tm)
                        break
                    else:
                        hybrid_handled = True

                next_format = self.formats[self.format_order[next_ndx]][1][0]
                s = strftimeEx(next_format, t, tm)

            if self.strip_leading_zeros:
                ss = s.lstrip('0')
                if ss != s and (ss == '' or not ss[0].isdigit()):
                    # A label such as '000ms' should leave one zero.
                    ss = '0' + ss
                labels.append(ss)
            else:
                labels.append(s)