<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def chunks(self,local,cutter_callback=None,*cutter_callback_args,**cutter_callback_kwargs):
 """ Takes a time range and returns sub timeranges based upon the cuts that cutter callback provides :param local: if False [default] use UTC datetime. If True use localtz :param cutter_callback: This should be a callback function that takes the current TimeRange and returns a list of DateTimes that denote where the next chunk should start. By default the cutter used will cut at 00:00:00 each day. """


        # First we get all the slices we want to take out of this time range.
        if not cutter_callback:
            cutter_callback = time_range_cutter_at_time
        time_cuts = cutter_callback(local,self,*cutter_callback_args,**cutter_callback_kwargs)

        # Now we need to make the time range objects for the cuts
        time_chunks = []
        time_index = self.start_time
        time_cuts = sorted(time_cuts)
        for time_cut in time_cuts:

            # FIXME: Better error message is probably going to be helpful
            if self.end_time < time_cut or self.start_time > time_cut:
                raise Exception('Cut time provided that is outside of time range')

            # Create the new tail end entry for times, combine it with the
            # index to craft a timerange and add it to the chunk list
            cut_end_time = time_cut

            # If the chunk is not the final chunk, we want to pull
            # the time back by a small smidgen
            if cut_end_time != self.end_time:
                cut_end_time -= datetime.timedelta(microseconds=1)

            time_ending = DateTime(
                            data=cut_end_time,
                            data_tz=time_index.local_tz,
                            local_tz=time_index.local_tz
                            )


            chunk_range = TimeRange(time_index,time_ending)
            time_chunks.append(chunk_range)

            # Setup the index for the next cut (the current cut
            # becomes the start of the next cut)
            time_index = DateTime(
                            data=time_cut,
                            data_tz=time_index.local_tz,
                            local_tz=time_index.local_tz
                        )

        # Add the last segment if required
        if time_index != self.end_time:
            time_chunks.append(
                TimeRange(time_index,self.end_time)
            )

        return time_chunks