Repository: Shusshu/Android-RecurrencePicker
Branch: master
Commit: 4f0ae74482e4
Files: 135
Total size: 794.7 KB
Directory structure:
gitextract_fk9y8ksi/
├── .gitignore
├── LICENSE.txt
├── README.md
├── demo/
│ ├── pom.xml
│ ├── project.properties
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── be/
│ │ └── billington/
│ │ └── calendar/
│ │ └── recurrencepicker/
│ │ └── demo/
│ │ └── activity/
│ │ └── DemoActivity.java
│ └── res/
│ ├── layout/
│ │ └── demo.xml
│ └── values/
│ ├── colors.xml
│ └── strings.xml
├── library/
│ ├── pom.xml
│ ├── project.properties
│ ├── release.properties
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── be/
│ │ └── billington/
│ │ └── calendar/
│ │ └── recurrencepicker/
│ │ ├── EventRecurrence.java
│ │ ├── EventRecurrenceFormatter.java
│ │ ├── LinearLayoutWithMaxWidth.java
│ │ ├── RecurrencePickerDialog.java
│ │ ├── Utils.java
│ │ └── WeekButton.java
│ └── res/
│ ├── color/
│ │ ├── done_text_color.xml
│ │ ├── recurrence_bubble_text_color.xml
│ │ └── recurrence_spinner_text_color.xml
│ ├── drawable/
│ │ ├── recurrence_bubble_fill.xml
│ │ └── switch_thumb.xml
│ ├── layout/
│ │ ├── recurrencepicker.xml
│ │ ├── recurrencepicker_end_text.xml
│ │ └── recurrencepicker_freq_item.xml
│ ├── values/
│ │ ├── arrays.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── values-af/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-am/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-ar/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-be/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-bg/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-ca/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-cs/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-da/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-de/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-el/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-en-rGB/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-es/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-es-rUS/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-et/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-fa/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-fi/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-fr/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-hi/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-hr/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-hu/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-in/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-it/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-iw/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-ja/
│ │ ├── arrays.xml
│ │ ├── colors.xml
│ │ └── strings.xml
│ ├── values-ko/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-land/
│ │ └── dimens.xml
│ ├── values-lt/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-lv/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-mcc262/
│ │ └── strings.xml
│ ├── values-ms/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-nb/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-nl/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-pl/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-pt/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-pt-rPT/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-ro/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-ru/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-sk/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-sl/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-sr/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-sv/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-sw/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-sw600dp/
│ │ └── dimens.xml
│ ├── values-sw600dp-land/
│ │ └── dimens.xml
│ ├── values-th/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-tl/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-tr/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-uk/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-vi/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-zh-rCN/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-zh-rTW/
│ │ ├── arrays.xml
│ │ └── strings.xml
│ └── values-zu/
│ ├── arrays.xml
│ └── strings.xml
└── pom.xml
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# built application files
*.apk
*.ap_
# files for the dex VM
*.dex
# Java class files
*.class
# generated files
bin/
gen/
out/
gen-external-apklibs/
# Local configuration file (sdk path, etc)
local.properties
# Eclipse project files
.classpath
.project
.settings
# Proguard folder generated by Eclipse
proguard/
# Intellij project files
*.iml
*.ipr
*.iws
.idea/
# Mac OS X files
*.DS_Store
# Maven
target
#Python
.pydevproject
#Crashlytics
com_crashlytics_export_strings.xml
#gradle
.gradle
build/
*.*~
================================================
FILE: LICENSE.txt
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
Android Recurrence Picker
=========================
Google Calendar Recurrence picker
Screenshot
==========
![Example Image][1]
Usage
=====
Maven / Gradle
--------------

Maven:
be.billington.calendar.recurrencepickerlibrary1.1.1aar
Gradle:
compile 'be.billington.calendar.recurrencepicker:library:1.1.1'
Credits
=======
This library uses Google Calendar Date & Time pickers from [Laurent Flavien & Edison Wang's library][2]
The original source code of the recurrence picker can be found [here][3]
License
=======
[The Apache Software License, Version 2.0][4]
[1]: https://github.com/Shusshu/Android-RecurrencePicker/blob/master/screenshots/recurrence-picker.png
[2]: https://github.com/flavienlaurent/datetimepicker
[3]: https://github.com/android/platform_packages_apps_calendar/tree/master/src/com/android/calendar
[4]: http://www.apache.org/licenses/LICENSE-2.0.txt
================================================
FILE: demo/pom.xml
================================================
4.0.0be.billington.calendar.recurrencepickerparent1.1.2-SNAPSHOTAndroid Date Time Picker - Demodemoapkcom.google.androidandroid4.1.1.4providedbe.billington.calendar.recurrencepickerlibrary${project.parent.version}aarjoda-timejoda-time2.3com.simpligility.maven.pluginsandroid-maven-plugintruetrue${sdk.platform}truetrueorg.apache.maven.pluginsmaven-compiler-plugin${java.version}${java.version}org.apache.maven.pluginsmaven-source-pluginattach-sourcespackagejarorg.apache.maven.pluginsmaven-scm-plugindeveloperConnection
================================================
FILE: demo/project.properties
================================================
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19
================================================
FILE: demo/src/main/AndroidManifest.xml
================================================
================================================
FILE: demo/src/main/java/be/billington/calendar/recurrencepicker/demo/activity/DemoActivity.java
================================================
package be.billington.calendar.recurrencepicker.demo.activity;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.text.format.Time;
import android.view.View;
import android.widget.TextView;
import be.billington.calendar.recurrencepicker.EventRecurrence;
import be.billington.calendar.recurrencepicker.EventRecurrenceFormatter;
import be.billington.calendar.recurrencepicker.RecurrencePickerDialog;
import be.billington.calendar.recurrencepicker.demo.R;
import java.util.Date;
public class DemoActivity extends FragmentActivity {
private TextView recurrence;
private String recurrenceRule;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo);
recurrence = (TextView) findViewById(R.id.recurrence);
recurrence.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RecurrencePickerDialog recurrencePickerDialog = new RecurrencePickerDialog();
if (recurrenceRule != null && recurrenceRule.length() > 0) {
Bundle bundle = new Bundle();
bundle.putString(RecurrencePickerDialog.BUNDLE_RRULE, recurrenceRule);
recurrencePickerDialog.setArguments(bundle);
}
recurrencePickerDialog.setOnRecurrenceSetListener(new RecurrencePickerDialog.OnRecurrenceSetListener() {
@Override
public void onRecurrenceSet(String rrule) {
recurrenceRule = rrule;
if (recurrenceRule != null && recurrenceRule.length() > 0) {
EventRecurrence recurrenceEvent = new EventRecurrence();
recurrenceEvent.setStartDate(new Time("" + new Date().getTime()));
recurrenceEvent.parse(rrule);
String srt = EventRecurrenceFormatter.getRepeatString(DemoActivity.this, getResources(), recurrenceEvent, true);
recurrence.setText(srt);
} else {
recurrence.setText("No recurrence");
}
}
});
recurrencePickerDialog.show(getSupportFragmentManager(), "recurrencePicker");
}
});
}
}
================================================
FILE: demo/src/main/res/layout/demo.xml
================================================
================================================
FILE: demo/src/main/res/values/colors.xml
================================================
#FFFFFF#000000#5bba1e#B2000000#99000000#7F000000#72000000#66000000#4C000000#33000000#19000000#99ff0000#00000000#99ffffff#7FFFFFFF#8000aeef#CC292e2c#665bba1e#1969bd45
================================================
FILE: demo/src/main/res/values/strings.xml
================================================
Android Recurrence Picker - Demo
================================================
FILE: library/pom.xml
================================================
4.0.0be.billington.calendar.recurrencepickerparent1.1.2-SNAPSHOTAndroid Recurrence Picker - Librarylibraryaarandroidandroid${android.version}providedcom.nineoldandroidslibrary2.4.0com.android.supportsupport-v421.0.3aarcom.github.flavienlaurent.datetimepickerlibrary0.0.2aarcom.android.supportsupport-v4com.simpligility.maven.pluginsandroid-maven-plugintruetrue${sdk.platform}org.apache.maven.pluginsmaven-source-pluginattach-sourcesverifyjar-no-fork
================================================
FILE: library/project.properties
================================================
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19
android.library=true
================================================
FILE: library/release.properties
================================================
#release configuration
#Mon Jan 20 16:21:01 CET 2014
preparationGoals=clean verify
pushChanges=true
scm.commentPrefix=[maven-release-plugin]
remoteTagging=true
exec.additionalArguments=-Psonatype-oss-release
completedPhase=scm-check-modifications
scm.url=scm\:git\:git@github.com\:Shusshu/Android-RecurrencePicker.git/library
================================================
FILE: library/src/main/AndroidManifest.xml
================================================
================================================
FILE: library/src/main/java/be/billington/calendar/recurrencepicker/EventRecurrence.java
================================================
package be.billington.calendar.recurrencepicker;
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.text.TextUtils;
import android.text.format.Time;
import android.util.Log;
import android.util.TimeFormatException;
import java.util.Calendar;
import java.util.HashMap;
/**
* Event recurrence utility functions.
*/
public class EventRecurrence {
private static String TAG = "EventRecur";
public static final int SECONDLY = 1;
public static final int MINUTELY = 2;
public static final int HOURLY = 3;
public static final int DAILY = 4;
public static final int WEEKLY = 5;
public static final int MONTHLY = 6;
public static final int YEARLY = 7;
public static final int SU = 0x00010000;
public static final int MO = 0x00020000;
public static final int TU = 0x00040000;
public static final int WE = 0x00080000;
public static final int TH = 0x00100000;
public static final int FR = 0x00200000;
public static final int SA = 0x00400000;
public Time startDate; // set by setStartDate(), not parse()
public int freq; // SECONDLY, MINUTELY, etc.
public String until;
public int count;
public int interval;
public int wkst; // SU, MO, TU, etc.
/* lists with zero entries may be null references */
public int[] bysecond;
public int bysecondCount;
public int[] byminute;
public int byminuteCount;
public int[] byhour;
public int byhourCount;
public int[] byday;
public int[] bydayNum;
public int bydayCount;
public int[] bymonthday;
public int bymonthdayCount;
public int[] byyearday;
public int byyeardayCount;
public int[] byweekno;
public int byweeknoCount;
public int[] bymonth;
public int bymonthCount;
public int[] bysetpos;
public int bysetposCount;
/**
* maps a part string to a parser object
*/
private static HashMap sParsePartMap;
static {
sParsePartMap = new HashMap();
sParsePartMap.put("FREQ", new ParseFreq());
sParsePartMap.put("UNTIL", new ParseUntil());
sParsePartMap.put("COUNT", new ParseCount());
sParsePartMap.put("INTERVAL", new ParseInterval());
sParsePartMap.put("BYSECOND", new ParseBySecond());
sParsePartMap.put("BYMINUTE", new ParseByMinute());
sParsePartMap.put("BYHOUR", new ParseByHour());
sParsePartMap.put("BYDAY", new ParseByDay());
sParsePartMap.put("BYMONTHDAY", new ParseByMonthDay());
sParsePartMap.put("BYYEARDAY", new ParseByYearDay());
sParsePartMap.put("BYWEEKNO", new ParseByWeekNo());
sParsePartMap.put("BYMONTH", new ParseByMonth());
sParsePartMap.put("BYSETPOS", new ParseBySetPos());
sParsePartMap.put("WKST", new ParseWkst());
}
/* values for bit vector that keeps track of what we have already seen */
private static final int PARSED_FREQ = 1 << 0;
private static final int PARSED_UNTIL = 1 << 1;
private static final int PARSED_COUNT = 1 << 2;
private static final int PARSED_INTERVAL = 1 << 3;
private static final int PARSED_BYSECOND = 1 << 4;
private static final int PARSED_BYMINUTE = 1 << 5;
private static final int PARSED_BYHOUR = 1 << 6;
private static final int PARSED_BYDAY = 1 << 7;
private static final int PARSED_BYMONTHDAY = 1 << 8;
private static final int PARSED_BYYEARDAY = 1 << 9;
private static final int PARSED_BYWEEKNO = 1 << 10;
private static final int PARSED_BYMONTH = 1 << 11;
private static final int PARSED_BYSETPOS = 1 << 12;
private static final int PARSED_WKST = 1 << 13;
/**
* maps a FREQ value to an integer constant
*/
private static final HashMap sParseFreqMap = new HashMap();
static {
sParseFreqMap.put("SECONDLY", SECONDLY);
sParseFreqMap.put("MINUTELY", MINUTELY);
sParseFreqMap.put("HOURLY", HOURLY);
sParseFreqMap.put("DAILY", DAILY);
sParseFreqMap.put("WEEKLY", WEEKLY);
sParseFreqMap.put("MONTHLY", MONTHLY);
sParseFreqMap.put("YEARLY", YEARLY);
}
/**
* maps a two-character weekday string to an integer constant
*/
private static final HashMap sParseWeekdayMap = new HashMap();
static {
sParseWeekdayMap.put("SU", SU);
sParseWeekdayMap.put("MO", MO);
sParseWeekdayMap.put("TU", TU);
sParseWeekdayMap.put("WE", WE);
sParseWeekdayMap.put("TH", TH);
sParseWeekdayMap.put("FR", FR);
sParseWeekdayMap.put("SA", SA);
}
/**
* If set, allow lower-case recurrence rule strings. Minor performance impact.
*/
private static final boolean ALLOW_LOWER_CASE = true;
/**
* If set, validate the value of UNTIL parts. Minor performance impact.
*/
private static final boolean VALIDATE_UNTIL = false;
/**
* If set, require that only one of {UNTIL,COUNT} is present. Breaks compat w/ old parser.
*/
private static final boolean ONLY_ONE_UNTIL_COUNT = false;
/**
* Thrown when a recurrence string provided can not be parsed according
* to RFC2445.
*/
public static class InvalidFormatException extends RuntimeException {
InvalidFormatException(String s) {
super(s);
}
}
public void setStartDate(Time date) {
startDate = date;
}
/**
* Converts one of the Calendar.SUNDAY constants to the SU, MO, etc.
* constants. btw, I think we should switch to those here too, to
* get rid of this function, if possible.
*/
public static int calendarDay2Day(int day) {
switch (day) {
case Calendar.SUNDAY:
return SU;
case Calendar.MONDAY:
return MO;
case Calendar.TUESDAY:
return TU;
case Calendar.WEDNESDAY:
return WE;
case Calendar.THURSDAY:
return TH;
case Calendar.FRIDAY:
return FR;
case Calendar.SATURDAY:
return SA;
default:
throw new RuntimeException("bad day of week: " + day);
}
}
public static int timeDay2Day(int day) {
switch (day) {
case Time.SUNDAY:
return SU;
case Time.MONDAY:
return MO;
case Time.TUESDAY:
return TU;
case Time.WEDNESDAY:
return WE;
case Time.THURSDAY:
return TH;
case Time.FRIDAY:
return FR;
case Time.SATURDAY:
return SA;
default:
throw new RuntimeException("bad day of week: " + day);
}
}
public static int day2TimeDay(int day) {
switch (day) {
case SU:
return Time.SUNDAY;
case MO:
return Time.MONDAY;
case TU:
return Time.TUESDAY;
case WE:
return Time.WEDNESDAY;
case TH:
return Time.THURSDAY;
case FR:
return Time.FRIDAY;
case SA:
return Time.SATURDAY;
default:
throw new RuntimeException("bad day of week: " + day);
}
}
/**
* Converts one of the SU, MO, etc. constants to the Calendar.SUNDAY
* constants. btw, I think we should switch to those here too, to
* get rid of this function, if possible.
*/
public static int day2CalendarDay(int day) {
switch (day) {
case SU:
return Calendar.SUNDAY;
case MO:
return Calendar.MONDAY;
case TU:
return Calendar.TUESDAY;
case WE:
return Calendar.WEDNESDAY;
case TH:
return Calendar.THURSDAY;
case FR:
return Calendar.FRIDAY;
case SA:
return Calendar.SATURDAY;
default:
throw new RuntimeException("bad day of week: " + day);
}
}
/**
* Converts one of the internal day constants (SU, MO, etc.) to the
* two-letter string representing that constant.
*
* @param day one the internal constants SU, MO, etc.
* @return the two-letter string for the day ("SU", "MO", etc.)
* @throws IllegalArgumentException Thrown if the day argument is not one of
* the defined day constants.
*/
private static String day2String(int day) {
switch (day) {
case SU:
return "SU";
case MO:
return "MO";
case TU:
return "TU";
case WE:
return "WE";
case TH:
return "TH";
case FR:
return "FR";
case SA:
return "SA";
default:
throw new IllegalArgumentException("bad day argument: " + day);
}
}
private static void appendNumbers(StringBuilder s, String label,
int count, int[] values) {
if (count > 0) {
s.append(label);
count--;
for (int i = 0; i < count; i++) {
s.append(values[i]);
s.append(",");
}
s.append(values[count]);
}
}
private void appendByDay(StringBuilder s, int i) {
int n = this.bydayNum[i];
if (n != 0) {
s.append(n);
}
String str = day2String(this.byday[i]);
s.append(str);
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
s.append("FREQ=");
switch (this.freq) {
case SECONDLY:
s.append("SECONDLY");
break;
case MINUTELY:
s.append("MINUTELY");
break;
case HOURLY:
s.append("HOURLY");
break;
case DAILY:
s.append("DAILY");
break;
case WEEKLY:
s.append("WEEKLY");
break;
case MONTHLY:
s.append("MONTHLY");
break;
case YEARLY:
s.append("YEARLY");
break;
}
if (!TextUtils.isEmpty(this.until)) {
s.append(";UNTIL=");
s.append(until);
}
if (this.count != 0) {
s.append(";COUNT=");
s.append(this.count);
}
if (this.interval != 0) {
s.append(";INTERVAL=");
s.append(this.interval);
}
if (this.wkst != 0) {
s.append(";WKST=");
s.append(day2String(this.wkst));
}
appendNumbers(s, ";BYSECOND=", this.bysecondCount, this.bysecond);
appendNumbers(s, ";BYMINUTE=", this.byminuteCount, this.byminute);
appendNumbers(s, ";BYSECOND=", this.byhourCount, this.byhour);
// day
int count = this.bydayCount;
if (count > 0) {
s.append(";BYDAY=");
count--;
for (int i = 0; i < count; i++) {
appendByDay(s, i);
s.append(",");
}
appendByDay(s, count);
}
appendNumbers(s, ";BYMONTHDAY=", this.bymonthdayCount, this.bymonthday);
appendNumbers(s, ";BYYEARDAY=", this.byyeardayCount, this.byyearday);
appendNumbers(s, ";BYWEEKNO=", this.byweeknoCount, this.byweekno);
appendNumbers(s, ";BYMONTH=", this.bymonthCount, this.bymonth);
appendNumbers(s, ";BYSETPOS=", this.bysetposCount, this.bysetpos);
return s.toString();
}
public boolean repeatsOnEveryWeekDay() {
if (this.freq != WEEKLY) {
return false;
}
int count = this.bydayCount;
if (count != 5) {
return false;
}
for (int i = 0; i < count; i++) {
int day = byday[i];
if (day == SU || day == SA) {
return false;
}
}
return true;
}
/**
* Determines whether this rule specifies a simple monthly rule by weekday, such as
* "FREQ=MONTHLY;BYDAY=3TU" (the 3rd Tuesday of every month).
*
* Negative days, e.g. "FREQ=MONTHLY;BYDAY=-1TU" (the last Tuesday of every month),
* will cause "false" to be returned.
*
* Rules that fire every week, such as "FREQ=MONTHLY;BYDAY=TU" (every Tuesday of every
* month) will cause "false" to be returned. (Note these are usually expressed as
* WEEKLY rules, and hence are uncommon.)
*
* @return true if this rule is of the appropriate form
*/
public boolean repeatsMonthlyOnDayCount() {
if (this.freq != MONTHLY) {
return false;
}
if (bydayCount != 1 || bymonthdayCount != 0) {
return false;
}
if (bydayNum[0] <= 0) {
return false;
}
return true;
}
/**
* Determines whether two integer arrays contain identical elements.
*
* The native implementation over-allocated the arrays (and may have stuff left over from
* a previous run), so we can't just check the arrays -- the separately-maintained count
* field also matters. We assume that a null array will have a count of zero, and that the
* array can hold as many elements as the associated count indicates.
*
* TODO: replace this with Arrays.equals() when the old parser goes away.
*/
private static boolean arraysEqual(int[] array1, int count1, int[] array2, int count2) {
if (count1 != count2) {
return false;
}
for (int i = 0; i < count1; i++) {
if (array1[i] != array2[i])
return false;
}
return true;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof EventRecurrence)) {
return false;
}
EventRecurrence er = (EventRecurrence) obj;
return (startDate == null ?
er.startDate == null : Time.compare(startDate, er.startDate) == 0) &&
freq == er.freq &&
(until == null ? er.until == null : until.equals(er.until)) &&
count == er.count &&
interval == er.interval &&
wkst == er.wkst &&
arraysEqual(bysecond, bysecondCount, er.bysecond, er.bysecondCount) &&
arraysEqual(byminute, byminuteCount, er.byminute, er.byminuteCount) &&
arraysEqual(byhour, byhourCount, er.byhour, er.byhourCount) &&
arraysEqual(byday, bydayCount, er.byday, er.bydayCount) &&
arraysEqual(bydayNum, bydayCount, er.bydayNum, er.bydayCount) &&
arraysEqual(bymonthday, bymonthdayCount, er.bymonthday, er.bymonthdayCount) &&
arraysEqual(byyearday, byyeardayCount, er.byyearday, er.byyeardayCount) &&
arraysEqual(byweekno, byweeknoCount, er.byweekno, er.byweeknoCount) &&
arraysEqual(bymonth, bymonthCount, er.bymonth, er.bymonthCount) &&
arraysEqual(bysetpos, bysetposCount, er.bysetpos, er.bysetposCount);
}
@Override
public int hashCode() {
// We overrode equals, so we must override hashCode(). Nobody seems to need this though.
throw new UnsupportedOperationException();
}
/**
* Resets parser-modified fields to their initial state. Does not alter startDate.
*
* The original parser always set all of the "count" fields, "wkst", and "until",
* essentially allowing the same object to be used multiple times by calling parse().
* It's unclear whether this behavior was intentional. For now, be paranoid and
* preserve the existing behavior by resetting the fields.
*
* We don't need to touch the integer arrays; they will either be ignored or
* overwritten. The "startDate" field is not set by the parser, so we ignore it here.
*/
private void resetFields() {
until = null;
freq = count = interval = bysecondCount = byminuteCount = byhourCount =
bydayCount = bymonthdayCount = byyeardayCount = byweeknoCount = bymonthCount =
bysetposCount = 0;
}
/**
* Parses an rfc2445 recurrence rule string into its component pieces. Attempting to parse
* malformed input will result in an EventRecurrence.InvalidFormatException.
*
* @param recur The recurrence rule to parse (in un-folded form).
*/
public void parse(String recur) {
/*
* From RFC 2445 section 4.3.10:
*
* recur = "FREQ"=freq *(
* ; either UNTIL or COUNT may appear in a 'recur',
* ; but UNTIL and COUNT MUST NOT occur in the same 'recur'
*
* ( ";" "UNTIL" "=" enddate ) /
* ( ";" "COUNT" "=" 1*DIGIT ) /
*
* ; the rest of these keywords are optional,
* ; but MUST NOT occur more than once
*
* ( ";" "INTERVAL" "=" 1*DIGIT ) /
* ( ";" "BYSECOND" "=" byseclist ) /
* ( ";" "BYMINUTE" "=" byminlist ) /
* ( ";" "BYHOUR" "=" byhrlist ) /
* ( ";" "BYDAY" "=" bywdaylist ) /
* ( ";" "BYMONTHDAY" "=" bymodaylist ) /
* ( ";" "BYYEARDAY" "=" byyrdaylist ) /
* ( ";" "BYWEEKNO" "=" bywknolist ) /
* ( ";" "BYMONTH" "=" bymolist ) /
* ( ";" "BYSETPOS" "=" bysplist ) /
* ( ";" "WKST" "=" weekday ) /
* ( ";" x-name "=" text )
* )
*
* The rule parts are not ordered in any particular sequence.
*
* Examples:
* FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU
* FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8
*
* Strategy:
* (1) Split the string at ';' boundaries to get an array of rule "parts".
* (2) For each part, find substrings for left/right sides of '=' (name/value).
* (3) Call a -specific parsing function to parse the into an
* output field.
*
* By keeping track of which names we've seen in a bit vector, we can verify the
* constraints indicated above (FREQ appears first, none of them appear more than once --
* though x-[name] would require special treatment), and we have either UNTIL or COUNT
* but not both.
*
* In general, RFC 2445 property names (e.g. "FREQ") and enumerations ("TU") must
* be handled in a case-insensitive fashion, but case may be significant for other
* properties. We don't have any case-sensitive values in RRULE, except possibly
* for the custom "X-" properties, but we ignore those anyway. Thus, we can trivially
* convert the entire string to upper case and then use simple comparisons.
*
* Differences from previous version:
* - allows lower-case property and enumeration values [optional]
* - enforces that FREQ appears first
* - enforces that only one of UNTIL and COUNT may be specified
* - allows (but ignores) X-* parts
* - improved validation on various values (e.g. UNTIL timestamps)
* - error messages are more specific
*
* TODO: enforce additional constraints listed in RFC 5545, notably the "N/A" entries
* in section 3.3.10. For example, if FREQ=WEEKLY, we should reject a rule that
* includes a BYMONTHDAY part.
*/
/* TODO: replace with "if (freq != 0) throw" if nothing requires this */
resetFields();
int parseFlags = 0;
String[] parts;
if (ALLOW_LOWER_CASE) {
parts = recur.toUpperCase().split(";");
} else {
parts = recur.split(";");
}
for (String part : parts) {
// allow empty part (e.g., double semicolon ";;")
if (TextUtils.isEmpty(part)) {
continue;
}
int equalIndex = part.indexOf('=');
if (equalIndex <= 0) {
/* no '=' or no LHS */
throw new InvalidFormatException("Missing LHS in " + part);
}
String lhs = part.substring(0, equalIndex);
String rhs = part.substring(equalIndex + 1);
if (rhs.length() == 0) {
throw new InvalidFormatException("Missing RHS in " + part);
}
/*
* In lieu of a "switch" statement that allows string arguments, we use a
* map from strings to parsing functions.
*/
PartParser parser = sParsePartMap.get(lhs);
if (parser == null) {
if (lhs.startsWith("X-")) {
//Log.d(TAG, "Ignoring custom part " + lhs);
continue;
}
throw new InvalidFormatException("Couldn't find parser for " + lhs);
} else {
int flag = parser.parsePart(rhs, this);
if ((parseFlags & flag) != 0) {
throw new InvalidFormatException("Part " + lhs + " was specified twice");
}
parseFlags |= flag;
}
}
// If not specified, week starts on Monday.
if ((parseFlags & PARSED_WKST) == 0) {
wkst = MO;
}
// FREQ is mandatory.
if ((parseFlags & PARSED_FREQ) == 0) {
throw new InvalidFormatException("Must specify a FREQ value");
}
// Can't have both UNTIL and COUNT.
if ((parseFlags & (PARSED_UNTIL | PARSED_COUNT)) == (PARSED_UNTIL | PARSED_COUNT)) {
if (ONLY_ONE_UNTIL_COUNT) {
throw new InvalidFormatException("Must not specify both UNTIL and COUNT: " + recur);
} else {
Log.w(TAG, "Warning: rrule has both UNTIL and COUNT: " + recur);
}
}
}
/**
* Base class for the RRULE part parsers.
*/
abstract static class PartParser {
/**
* Parses a single part.
*
* @param value The right-hand-side of the part.
* @param er The EventRecurrence into which the result is stored.
* @return A bit value indicating which part was parsed.
*/
public abstract int parsePart(String value, EventRecurrence er);
/**
* Parses an integer, with range-checking.
*
* @param str The string to parse.
* @param minVal Minimum allowed value.
* @param maxVal Maximum allowed value.
* @param allowZero Is 0 allowed?
* @return The parsed value.
*/
public static int parseIntRange(String str, int minVal, int maxVal, boolean allowZero) {
try {
if (str.charAt(0) == '+') {
// Integer.parseInt does not allow a leading '+', so skip it manually.
str = str.substring(1);
}
int val = Integer.parseInt(str);
if (val < minVal || val > maxVal || (val == 0 && !allowZero)) {
throw new InvalidFormatException("Integer value out of range: " + str);
}
return val;
} catch (NumberFormatException nfe) {
throw new InvalidFormatException("Invalid integer value: " + str);
}
}
/**
* Parses a comma-separated list of integers, with range-checking.
*
* @param listStr The string to parse.
* @param minVal Minimum allowed value.
* @param maxVal Maximum allowed value.
* @param allowZero Is 0 allowed?
* @return A new array with values, sized to hold the exact number of elements.
*/
public static int[] parseNumberList(String listStr, int minVal, int maxVal,
boolean allowZero) {
int[] values;
if (listStr.indexOf(",") < 0) {
// Common case: only one entry, skip split() overhead.
values = new int[1];
values[0] = parseIntRange(listStr, minVal, maxVal, allowZero);
} else {
String[] valueStrs = listStr.split(",");
int len = valueStrs.length;
values = new int[len];
for (int i = 0; i < len; i++) {
values[i] = parseIntRange(valueStrs[i], minVal, maxVal, allowZero);
}
}
return values;
}
}
/**
* parses FREQ={SECONDLY,MINUTELY,...}
*/
private static class ParseFreq extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
Integer freq = sParseFreqMap.get(value);
if (freq == null) {
throw new InvalidFormatException("Invalid FREQ value: " + value);
}
er.freq = freq;
return PARSED_FREQ;
}
}
/**
* parses UNTIL=enddate, e.g. "19970829T021400"
*/
private static class ParseUntil extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
if (VALIDATE_UNTIL) {
try {
// Parse the time to validate it. The result isn't retained.
Time until = new Time();
until.parse(value);
} catch (TimeFormatException tfe) {
throw new InvalidFormatException("Invalid UNTIL value: " + value);
}
}
er.until = value;
return PARSED_UNTIL;
}
}
/**
* parses COUNT=[non-negative-integer]
*/
private static class ParseCount extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
er.count = parseIntRange(value, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
if (er.count < 0) {
Log.d(TAG, "Invalid Count. Forcing COUNT to 1 from " + value);
er.count = 1; // invalid count. assume one time recurrence.
}
return PARSED_COUNT;
}
}
/**
* parses INTERVAL=[non-negative-integer]
*/
private static class ParseInterval extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
er.interval = parseIntRange(value, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
if (er.interval < 1) {
Log.d(TAG, "Invalid Interval. Forcing INTERVAL to 1 from " + value);
er.interval = 1;
}
return PARSED_INTERVAL;
}
}
/**
* parses BYSECOND=byseclist
*/
private static class ParseBySecond extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
int[] bysecond = parseNumberList(value, 0, 59, true);
er.bysecond = bysecond;
er.bysecondCount = bysecond.length;
return PARSED_BYSECOND;
}
}
/**
* parses BYMINUTE=byminlist
*/
private static class ParseByMinute extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
int[] byminute = parseNumberList(value, 0, 59, true);
er.byminute = byminute;
er.byminuteCount = byminute.length;
return PARSED_BYMINUTE;
}
}
/**
* parses BYHOUR=byhrlist
*/
private static class ParseByHour extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
int[] byhour = parseNumberList(value, 0, 23, true);
er.byhour = byhour;
er.byhourCount = byhour.length;
return PARSED_BYHOUR;
}
}
/**
* parses BYDAY=bywdaylist, e.g. "1SU,-1SU"
*/
private static class ParseByDay extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
int[] byday;
int[] bydayNum;
int bydayCount;
if (value.indexOf(",") < 0) {
/* only one entry, skip split() overhead */
bydayCount = 1;
byday = new int[1];
bydayNum = new int[1];
parseWday(value, byday, bydayNum, 0);
} else {
String[] wdays = value.split(",");
int len = wdays.length;
bydayCount = len;
byday = new int[len];
bydayNum = new int[len];
for (int i = 0; i < len; i++) {
parseWday(wdays[i], byday, bydayNum, i);
}
}
er.byday = byday;
er.bydayNum = bydayNum;
er.bydayCount = bydayCount;
return PARSED_BYDAY;
}
/**
* parses [int]weekday, putting the pieces into parallel array entries
*/
private static void parseWday(String str, int[] byday, int[] bydayNum, int index) {
int wdayStrStart = str.length() - 2;
String wdayStr;
if (wdayStrStart > 0) {
/* number is included; parse it out and advance to weekday */
String numPart = str.substring(0, wdayStrStart);
int num = parseIntRange(numPart, -53, 53, false);
bydayNum[index] = num;
wdayStr = str.substring(wdayStrStart);
} else {
/* just the weekday string */
wdayStr = str;
}
Integer wday = sParseWeekdayMap.get(wdayStr);
if (wday == null) {
throw new InvalidFormatException("Invalid BYDAY value: " + str);
}
byday[index] = wday;
}
}
/**
* parses BYMONTHDAY=bymodaylist
*/
private static class ParseByMonthDay extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
int[] bymonthday = parseNumberList(value, -31, 31, false);
er.bymonthday = bymonthday;
er.bymonthdayCount = bymonthday.length;
return PARSED_BYMONTHDAY;
}
}
/**
* parses BYYEARDAY=byyrdaylist
*/
private static class ParseByYearDay extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
int[] byyearday = parseNumberList(value, -366, 366, false);
er.byyearday = byyearday;
er.byyeardayCount = byyearday.length;
return PARSED_BYYEARDAY;
}
}
/**
* parses BYWEEKNO=bywknolist
*/
private static class ParseByWeekNo extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
int[] byweekno = parseNumberList(value, -53, 53, false);
er.byweekno = byweekno;
er.byweeknoCount = byweekno.length;
return PARSED_BYWEEKNO;
}
}
/**
* parses BYMONTH=bymolist
*/
private static class ParseByMonth extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
int[] bymonth = parseNumberList(value, 1, 12, false);
er.bymonth = bymonth;
er.bymonthCount = bymonth.length;
return PARSED_BYMONTH;
}
}
/**
* parses BYSETPOS=bysplist
*/
private static class ParseBySetPos extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
int[] bysetpos = parseNumberList(value, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
er.bysetpos = bysetpos;
er.bysetposCount = bysetpos.length;
return PARSED_BYSETPOS;
}
}
/**
* parses WKST={SU,MO,...}
*/
private static class ParseWkst extends PartParser {
@Override
public int parsePart(String value, EventRecurrence er) {
Integer wkst = sParseWeekdayMap.get(value);
if (wkst == null) {
throw new InvalidFormatException("Invalid WKST value: " + value);
}
er.wkst = wkst;
return PARSED_WKST;
}
}
}
================================================
FILE: library/src/main/java/be/billington/calendar/recurrencepicker/EventRecurrenceFormatter.java
================================================
package be.billington.calendar.recurrencepicker;
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.content.Context;
import android.content.res.Resources;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.TimeFormatException;
import java.util.Calendar;
public class EventRecurrenceFormatter
{
private static int[] mMonthRepeatByDayOfWeekIds;
private static String[][] mMonthRepeatByDayOfWeekStrs;
public static String getRepeatString(Context context, Resources r, EventRecurrence recurrence,
boolean includeEndString) {
String endString = "";
if (includeEndString) {
StringBuilder sb = new StringBuilder();
if (recurrence.until != null) {
try {
Time t = new Time();
t.parse(recurrence.until);
final String dateStr = DateUtils.formatDateTime(context,
t.toMillis(false), DateUtils.FORMAT_NUMERIC_DATE);
sb.append(r.getString(R.string.endByDate, dateStr));
} catch (TimeFormatException e) {
}
}
if (recurrence.count > 0) {
sb.append(r.getQuantityString(R.plurals.endByCount, recurrence.count,
recurrence.count));
}
endString = sb.toString();
}
// TODO Implement "Until" portion of string, as well as custom settings
int interval = recurrence.interval <= 1 ? 1 : recurrence.interval;
switch (recurrence.freq) {
case EventRecurrence.DAILY:
return r.getQuantityString(R.plurals.daily, interval, interval) + endString;
case EventRecurrence.WEEKLY: {
if (recurrence.repeatsOnEveryWeekDay()) {
return r.getString(R.string.every_weekday) + endString;
} else {
String string;
int dayOfWeekLength = DateUtils.LENGTH_MEDIUM;
if (recurrence.bydayCount == 1) {
dayOfWeekLength = DateUtils.LENGTH_LONG;
}
StringBuilder days = new StringBuilder();
// Do one less iteration in the loop so the last element is added out of the
// loop. This is done so the comma is not placed after the last item.
if (recurrence.bydayCount > 0) {
int count = recurrence.bydayCount - 1;
for (int i = 0 ; i < count ; i++) {
days.append(dayToString(recurrence.byday[i], dayOfWeekLength));
days.append(", ");
}
days.append(dayToString(recurrence.byday[count], dayOfWeekLength));
string = days.toString();
} else {
// There is no "BYDAY" specifier, so use the day of the
// first event. For this to work, the setStartDate()
// method must have been used by the caller to set the
// date of the first event in the recurrence.
if (recurrence.startDate == null) {
return null;
}
int day = EventRecurrence.timeDay2Day(recurrence.startDate.weekDay);
string = dayToString(day, DateUtils.LENGTH_LONG);
}
return r.getQuantityString(R.plurals.weekly, interval, interval, string)
+ endString;
}
}
case EventRecurrence.MONTHLY: {
if (recurrence.bydayCount == 1) {
int weekday = recurrence.startDate.weekDay;
// Cache this stuff so we won't have to redo work again later.
cacheMonthRepeatStrings(r, weekday);
int dayNumber = (recurrence.startDate.monthDay - 1) / 7;
StringBuilder sb = new StringBuilder();
sb.append(r.getString(R.string.monthly));
sb.append(" (");
sb.append(mMonthRepeatByDayOfWeekStrs[weekday][dayNumber]);
sb.append(")");
sb.append(endString);
return sb.toString();
}
return r.getString(R.string.monthly) + endString;
}
case EventRecurrence.YEARLY:
return r.getString(R.string.yearly_plain) + endString;
}
return null;
}
private static void cacheMonthRepeatStrings(Resources r, int weekday) {
if (mMonthRepeatByDayOfWeekIds == null) {
mMonthRepeatByDayOfWeekIds = new int[7];
mMonthRepeatByDayOfWeekIds[0] = R.array.repeat_by_nth_sun;
mMonthRepeatByDayOfWeekIds[1] = R.array.repeat_by_nth_mon;
mMonthRepeatByDayOfWeekIds[2] = R.array.repeat_by_nth_tues;
mMonthRepeatByDayOfWeekIds[3] = R.array.repeat_by_nth_wed;
mMonthRepeatByDayOfWeekIds[4] = R.array.repeat_by_nth_thurs;
mMonthRepeatByDayOfWeekIds[5] = R.array.repeat_by_nth_fri;
mMonthRepeatByDayOfWeekIds[6] = R.array.repeat_by_nth_sat;
}
if (mMonthRepeatByDayOfWeekStrs == null) {
mMonthRepeatByDayOfWeekStrs = new String[7][];
}
if (mMonthRepeatByDayOfWeekStrs[weekday] == null) {
mMonthRepeatByDayOfWeekStrs[weekday] =
r.getStringArray(mMonthRepeatByDayOfWeekIds[weekday]);
}
}
/**
* Converts day of week to a String.
* @param day a EventRecurrence constant
* @return day of week as a string
*/
private static String dayToString(int day, int dayOfWeekLength) {
return DateUtils.getDayOfWeekString(dayToUtilDay(day), dayOfWeekLength);
}
/**
* Converts EventRecurrence's day of week to DateUtil's day of week.
* @param day of week as an EventRecurrence value
* @return day of week as a DateUtil value.
*/
private static int dayToUtilDay(int day) {
switch (day) {
case EventRecurrence.SU: return Calendar.SUNDAY;
case EventRecurrence.MO: return Calendar.MONDAY;
case EventRecurrence.TU: return Calendar.TUESDAY;
case EventRecurrence.WE: return Calendar.WEDNESDAY;
case EventRecurrence.TH: return Calendar.THURSDAY;
case EventRecurrence.FR: return Calendar.FRIDAY;
case EventRecurrence.SA: return Calendar.SATURDAY;
default: throw new IllegalArgumentException("bad day argument: " + day);
}
}
}
================================================
FILE: library/src/main/java/be/billington/calendar/recurrencepicker/LinearLayoutWithMaxWidth.java
================================================
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package be.billington.calendar.recurrencepicker;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
public class LinearLayoutWithMaxWidth extends LinearLayout {
public LinearLayoutWithMaxWidth(Context context) {
super(context);
}
public LinearLayoutWithMaxWidth(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LinearLayoutWithMaxWidth(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
WeekButton.setSuggestedWidth((View.MeasureSpec.getSize(widthMeasureSpec)) / 7);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
================================================
FILE: library/src/main/java/be/billington/calendar/recurrencepicker/RecurrencePickerDialog.java
================================================
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package be.billington.calendar.recurrencepicker;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.app.DialogFragment;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Log;
import android.util.TimeFormatException;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import com.fourmob.datetimepicker.date.DatePickerDialog;
import java.text.DateFormatSymbols;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
public class RecurrencePickerDialog extends DialogFragment implements OnItemSelectedListener,
OnCheckedChangeListener, OnClickListener,
android.widget.RadioGroup.OnCheckedChangeListener, DatePickerDialog.OnDateSetListener {
private static final String TAG = "RecurrencePickerDialog";
// in dp's
private static final int MIN_SCREEN_WIDTH_FOR_SINGLE_ROW_WEEK = 450;
// Update android:maxLength in EditText as needed
private static final int INTERVAL_MAX = 99;
private static final int INTERVAL_DEFAULT = 1;
// Update android:maxLength in EditText as needed
private static final int COUNT_MAX = 730;
private static final int COUNT_DEFAULT = 5;
// Special cases in monthlyByNthDayOfWeek
private static final int FIFTH_WEEK_IN_A_MONTH = 5;
private static final int LAST_NTH_DAY_OF_WEEK = -1;
private DatePickerDialog mDatePickerDialog;
private class RecurrenceModel implements Parcelable {
// Should match EventRecurrence.DAILY, etc
static final int FREQ_DAILY = 0;
static final int FREQ_WEEKLY = 1;
static final int FREQ_MONTHLY = 2;
static final int FREQ_YEARLY = 3;
static final int END_NEVER = 0;
static final int END_BY_DATE = 1;
static final int END_BY_COUNT = 2;
static final int MONTHLY_BY_DATE = 0;
static final int MONTHLY_BY_NTH_DAY_OF_WEEK = 1;
static final int STATE_NO_RECURRENCE = 0;
static final int STATE_RECURRENCE = 1;
int recurrenceState;
/**
* FREQ: Repeat pattern
*
* @see FREQ_DAILY
* @see FREQ_WEEKLY
* @see FREQ_MONTHLY
* @see FREQ_YEARLY
*/
int freq = FREQ_WEEKLY;
/**
* INTERVAL: Every n days/weeks/months/years. n >= 1
*/
int interval = INTERVAL_DEFAULT;
/**
* UNTIL and COUNT: How does the the event end?
*
* @see END_NEVER
* @see END_BY_DATE
* @see END_BY_COUNT
* @see untilDate
* @see untilCount
*/
int end;
/**
* UNTIL: Date of the last recurrence. Used when until == END_BY_DATE
*/
Time endDate;
/**
* COUNT: Times to repeat. Use when until == END_BY_COUNT
*/
int endCount = COUNT_DEFAULT;
/**
* BYDAY: Days of the week to be repeated. Sun = 0, Mon = 1, etc
*/
boolean[] weeklyByDayOfWeek = new boolean[7];
/**
* BYDAY AND BYMONTHDAY: How to repeat monthly events? Same date of the
* month or Same nth day of week.
*
* @see MONTHLY_BY_DATE
* @see MONTHLY_BY_NTH_DAY_OF_WEEK
*/
int monthlyRepeat;
/**
* Day of the month to repeat. Used when monthlyRepeat ==
* MONTHLY_BY_DATE
*/
int monthlyByMonthDay;
/**
* Day of the week to repeat. Used when monthlyRepeat ==
* MONTHLY_BY_NTH_DAY_OF_WEEK
*/
int monthlyByDayOfWeek;
/**
* Nth day of the week to repeat. Used when monthlyRepeat ==
* MONTHLY_BY_NTH_DAY_OF_WEEK 0=undefined, -1=Last, 1=1st, 2=2nd, ..., 5=5th
*
* We support 5th, just to handle backwards capabilities with old bug, but it
* gets converted to -1 once edited.
*/
int monthlyByNthDayOfWeek;
/*
* (generated method)
*/
@Override
public String toString() {
return "Model [freq=" + freq + ", interval=" + interval + ", end=" + end + ", endDate="
+ endDate + ", endCount=" + endCount + ", weeklyByDayOfWeek="
+ Arrays.toString(weeklyByDayOfWeek) + ", monthlyRepeat=" + monthlyRepeat
+ ", monthlyByMonthDay=" + monthlyByMonthDay + ", monthlyByDayOfWeek="
+ monthlyByDayOfWeek + ", monthlyByNthDayOfWeek=" + monthlyByNthDayOfWeek + "]";
}
@Override
public int describeContents() {
return 0;
}
public RecurrenceModel() {
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(freq);
dest.writeInt(interval);
dest.writeInt(end);
dest.writeInt(endDate.year);
dest.writeInt(endDate.month);
dest.writeInt(endDate.monthDay);
dest.writeInt(endCount);
dest.writeBooleanArray(weeklyByDayOfWeek);
dest.writeInt(monthlyRepeat);
dest.writeInt(monthlyByMonthDay);
dest.writeInt(monthlyByDayOfWeek);
dest.writeInt(monthlyByNthDayOfWeek);
dest.writeInt(recurrenceState);
}
}
class minMaxTextWatcher implements TextWatcher {
private int mMin;
private int mMax;
private int mDefault;
public minMaxTextWatcher(int min, int defaultInt, int max) {
mMin = min;
mMax = max;
mDefault = defaultInt;
}
@Override
public void afterTextChanged(Editable s) {
boolean updated = false;
int value;
try {
value = Integer.parseInt(s.toString());
} catch (NumberFormatException e) {
value = mDefault;
}
if (value < mMin) {
value = mMin;
updated = true;
} else if (value > mMax) {
updated = true;
value = mMax;
}
// Update UI
if (updated) {
s.clear();
s.append(Integer.toString(value));
}
updateDoneButtonState();
onChange(value);
}
/**
* Override to be called after each key stroke
*/
void onChange(int value) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
}
private Resources mResources;
private EventRecurrence mRecurrence = new EventRecurrence();
private Time mTime = new Time(); // TODO timezone?
private RecurrenceModel mModel = new RecurrenceModel();
private Toast mToast;
private final int[] TIME_DAY_TO_CALENDAR_DAY = new int[]{
Calendar.SUNDAY,
Calendar.MONDAY,
Calendar.TUESDAY,
Calendar.WEDNESDAY,
Calendar.THURSDAY,
Calendar.FRIDAY,
Calendar.SATURDAY,
};
// Call mStringBuilder.setLength(0) before formatting any string or else the
// formatted text will accumulate.
// private final StringBuilder mStringBuilder = new StringBuilder();
// private Formatter mFormatter = new Formatter(mStringBuilder);
private View mView;
private Spinner mFreqSpinner;
private static final int[] mFreqModelToEventRecurrence = {
EventRecurrence.DAILY,
EventRecurrence.WEEKLY,
EventRecurrence.MONTHLY,
EventRecurrence.YEARLY
};
public static final String BUNDLE_START_TIME_MILLIS = "bundle_event_start_time";
public static final String BUNDLE_TIME_ZONE = "bundle_event_time_zone";
public static final String BUNDLE_RRULE = "bundle_event_rrule";
private static final String BUNDLE_MODEL = "bundle_model";
private static final String BUNDLE_END_COUNT_HAS_FOCUS = "bundle_end_count_has_focus";
private static final String FRAG_TAG_DATE_PICKER = "tag_date_picker_frag";
private Switch mRepeatSwitch;
private EditText mInterval;
private TextView mIntervalPreText;
private TextView mIntervalPostText;
private int mIntervalResId = -1;
private Spinner mEndSpinner;
private TextView mEndDateTextView;
private EditText mEndCount;
private TextView mPostEndCount;
private boolean mHidePostEndCount;
private ArrayList mEndSpinnerArray = new ArrayList(3);
private EndSpinnerAdapter mEndSpinnerAdapter;
private String mEndNeverStr;
private String mEndDateLabel;
private String mEndCountLabel;
/**
* Hold toggle buttons in the order per user's first day of week preference
*/
private LinearLayout mWeekGroup;
private LinearLayout mWeekGroup2;
// Sun = 0
private ToggleButton[] mWeekByDayButtons = new ToggleButton[7];
/**
* A double array of Strings to hold the 7x5 list of possible strings of the form:
* "on every [Nth] [DAY_OF_WEEK]", e.g. "on every second Monday",
* where [Nth] can be [first, second, third, fourth, last]
*/
private String[][] mMonthRepeatByDayOfWeekStrs;
private LinearLayout mMonthGroup;
private RadioGroup mMonthRepeatByRadioGroup;
private RadioButton mRepeatMonthlyByNthDayOfWeek;
private RadioButton mRepeatMonthlyByNthDayOfMonth;
private String mMonthRepeatByDayOfWeekStr;
private Button mDone;
private OnRecurrenceSetListener mRecurrenceSetListener;
public RecurrencePickerDialog() {
}
static public boolean isSupportedMonthlyByNthDayOfWeek(int num) {
// We only support monthlyByNthDayOfWeek when it is greater then 0 but less then 5.
// Or if -1 when it is the last monthly day of the week.
return (num > 0 && num <= FIFTH_WEEK_IN_A_MONTH) || num == LAST_NTH_DAY_OF_WEEK;
}
static public boolean canHandleRecurrenceRule(EventRecurrence er) {
switch (er.freq) {
case EventRecurrence.DAILY:
case EventRecurrence.MONTHLY:
case EventRecurrence.YEARLY:
case EventRecurrence.WEEKLY:
break;
default:
return false;
}
if (er.count > 0 && !TextUtils.isEmpty(er.until)) {
return false;
}
// Weekly: For "repeat by day of week", the day of week to repeat is in
// er.byday[]
/*
* Monthly: For "repeat by nth day of week" the day of week to repeat is
* in er.byday[] and the "nth" is stored in er.bydayNum[]. Currently we
* can handle only one and only in monthly
*/
int numOfByDayNum = 0;
for (int i = 0; i < er.bydayCount; i++) {
if (isSupportedMonthlyByNthDayOfWeek(er.bydayNum[i])) {
++numOfByDayNum;
}
}
if (numOfByDayNum > 1) {
return false;
}
if (numOfByDayNum > 0 && er.freq != EventRecurrence.MONTHLY) {
return false;
}
// The UI only handle repeat by one day of month i.e. not 9th and 10th
// of every month
if (er.bymonthdayCount > 1) {
return false;
}
if (er.freq == EventRecurrence.MONTHLY) {
if (er.bydayCount > 1) {
return false;
}
if (er.bydayCount > 0 && er.bymonthdayCount > 0) {
return false;
}
}
return true;
}
// TODO don't lose data when getting data that our UI can't handle
static private void copyEventRecurrenceToModel(final EventRecurrence er,
RecurrenceModel model) {
// Freq:
switch (er.freq) {
case EventRecurrence.DAILY:
model.freq = RecurrenceModel.FREQ_DAILY;
break;
case EventRecurrence.MONTHLY:
model.freq = RecurrenceModel.FREQ_MONTHLY;
break;
case EventRecurrence.YEARLY:
model.freq = RecurrenceModel.FREQ_YEARLY;
break;
case EventRecurrence.WEEKLY:
model.freq = RecurrenceModel.FREQ_WEEKLY;
break;
default:
throw new IllegalStateException("freq=" + er.freq);
}
// Interval:
if (er.interval > 0) {
model.interval = er.interval;
}
// End:
// End by count:
model.endCount = er.count;
if (model.endCount > 0) {
model.end = RecurrenceModel.END_BY_COUNT;
}
// End by date:
if (!TextUtils.isEmpty(er.until)) {
if (model.endDate == null) {
model.endDate = new Time();
}
try {
model.endDate.parse(er.until);
} catch (TimeFormatException e) {
model.endDate = null;
}
// LIMITATION: The UI can only handle END_BY_DATE or END_BY_COUNT
if (model.end == RecurrenceModel.END_BY_COUNT && model.endDate != null) {
throw new IllegalStateException("freq=" + er.freq);
}
model.end = RecurrenceModel.END_BY_DATE;
}
// Weekly: repeat by day of week or Monthly: repeat by nth day of week
// in the month
Arrays.fill(model.weeklyByDayOfWeek, false);
if (er.bydayCount > 0) {
int count = 0;
for (int i = 0; i < er.bydayCount; i++) {
int dayOfWeek = EventRecurrence.day2TimeDay(er.byday[i]);
model.weeklyByDayOfWeek[dayOfWeek] = true;
if (model.freq == RecurrenceModel.FREQ_MONTHLY &&
isSupportedMonthlyByNthDayOfWeek(er.bydayNum[i])) {
// LIMITATION: Can handle only (one) weekDayNum in nth or last and only
// when
// monthly
model.monthlyByDayOfWeek = dayOfWeek;
model.monthlyByNthDayOfWeek = er.bydayNum[i];
model.monthlyRepeat = RecurrenceModel.MONTHLY_BY_NTH_DAY_OF_WEEK;
count++;
}
}
if (model.freq == RecurrenceModel.FREQ_MONTHLY) {
if (er.bydayCount != 1) {
// Can't handle 1st Monday and 2nd Wed
throw new IllegalStateException("Can handle only 1 byDayOfWeek in monthly");
}
if (count != 1) {
throw new IllegalStateException(
"Didn't specify which nth day of week to repeat for a monthly");
}
}
}
// Monthly by day of month
if (model.freq == RecurrenceModel.FREQ_MONTHLY) {
if (er.bymonthdayCount == 1) {
if (model.monthlyRepeat == RecurrenceModel.MONTHLY_BY_NTH_DAY_OF_WEEK) {
throw new IllegalStateException(
"Can handle only by monthday or by nth day of week, not both");
}
model.monthlyByMonthDay = er.bymonthday[0];
model.monthlyRepeat = RecurrenceModel.MONTHLY_BY_DATE;
} else if (er.bymonthCount > 1) {
// LIMITATION: Can handle only one month day
throw new IllegalStateException("Can handle only one bymonthday");
}
}
}
static private void copyModelToEventRecurrence(final RecurrenceModel model,
EventRecurrence er) {
if (model.recurrenceState == RecurrenceModel.STATE_NO_RECURRENCE) {
throw new IllegalStateException("There's no recurrence");
}
// Freq
er.freq = mFreqModelToEventRecurrence[model.freq];
// Interval
if (model.interval <= 1) {
er.interval = 0;
} else {
er.interval = model.interval;
}
// End
switch (model.end) {
case RecurrenceModel.END_BY_DATE:
if (model.endDate != null) {
model.endDate.switchTimezone(Time.TIMEZONE_UTC);
model.endDate.normalize(false);
er.until = model.endDate.format2445();
er.count = 0;
} else {
throw new IllegalStateException("end = END_BY_DATE but endDate is null");
}
break;
case RecurrenceModel.END_BY_COUNT:
er.count = model.endCount;
er.until = null;
if (er.count <= 0) {
throw new IllegalStateException("count is " + er.count);
}
break;
default:
er.count = 0;
er.until = null;
break;
}
// Weekly && monthly repeat patterns
er.bydayCount = 0;
er.bymonthdayCount = 0;
switch (model.freq) {
case RecurrenceModel.FREQ_MONTHLY:
if (model.monthlyRepeat == RecurrenceModel.MONTHLY_BY_DATE) {
if (model.monthlyByMonthDay > 0) {
if (er.bymonthday == null || er.bymonthdayCount < 1) {
er.bymonthday = new int[1];
}
er.bymonthday[0] = model.monthlyByMonthDay;
er.bymonthdayCount = 1;
}
} else if (model.monthlyRepeat == RecurrenceModel.MONTHLY_BY_NTH_DAY_OF_WEEK) {
if (!isSupportedMonthlyByNthDayOfWeek(model.monthlyByNthDayOfWeek)) {
throw new IllegalStateException("month repeat by nth week but n is "
+ model.monthlyByNthDayOfWeek);
}
int count = 1;
if (er.bydayCount < count || er.byday == null || er.bydayNum == null) {
er.byday = new int[count];
er.bydayNum = new int[count];
}
er.bydayCount = count;
er.byday[0] = EventRecurrence.timeDay2Day(model.monthlyByDayOfWeek);
er.bydayNum[0] = model.monthlyByNthDayOfWeek;
}
break;
case RecurrenceModel.FREQ_WEEKLY:
int count = 0;
for (int i = 0; i < 7; i++) {
if (model.weeklyByDayOfWeek[i]) {
count++;
}
}
if (er.bydayCount < count || er.byday == null || er.bydayNum == null) {
er.byday = new int[count];
er.bydayNum = new int[count];
}
er.bydayCount = count;
for (int i = 6; i >= 0; i--) {
if (model.weeklyByDayOfWeek[i]) {
er.bydayNum[--count] = 0;
er.byday[count] = EventRecurrence.timeDay2Day(i);
}
}
break;
}
if (!canHandleRecurrenceRule(er)) {
throw new IllegalStateException("UI generated recurrence that it can't handle. ER:"
+ er.toString() + " Model: " + model.toString());
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mRecurrence.wkst = EventRecurrence.timeDay2Day(Utils.getFirstDayOfWeek(getActivity()));
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
boolean endCountHasFocus = false;
if (savedInstanceState != null) {
RecurrenceModel m = (RecurrenceModel) savedInstanceState.get(BUNDLE_MODEL);
if (m != null) {
mModel = m;
}
endCountHasFocus = savedInstanceState.getBoolean(BUNDLE_END_COUNT_HAS_FOCUS);
} else {
Bundle b = getArguments();
if (b != null) {
mTime.set(b.getLong(BUNDLE_START_TIME_MILLIS));
String tz = b.getString(BUNDLE_TIME_ZONE);
if (!TextUtils.isEmpty(tz)) {
mTime.timezone = tz;
}
mTime.normalize(false);
// Time days of week: Sun=0, Mon=1, etc
mModel.weeklyByDayOfWeek[mTime.weekDay] = true;
String rrule = b.getString(BUNDLE_RRULE);
if (!TextUtils.isEmpty(rrule)) {
mModel.recurrenceState = RecurrenceModel.STATE_RECURRENCE;
mRecurrence.parse(rrule);
copyEventRecurrenceToModel(mRecurrence, mModel);
// Leave today's day of week as checked by default in weekly view.
if (mRecurrence.bydayCount == 0) {
mModel.weeklyByDayOfWeek[mTime.weekDay] = true;
}
}
} else {
mTime.setToNow();
}
}
mResources = getResources();
mView = inflater.inflate(R.layout.recurrencepicker, container, true);
final Activity activity = getActivity();
final Configuration config = activity.getResources().getConfiguration();
mRepeatSwitch = (Switch) mView.findViewById(R.id.repeat_switch);
mRepeatSwitch.setChecked(mModel.recurrenceState == RecurrenceModel.STATE_RECURRENCE);
mRepeatSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mModel.recurrenceState = isChecked ? RecurrenceModel.STATE_RECURRENCE
: RecurrenceModel.STATE_NO_RECURRENCE;
togglePickerOptions();
}
});
mFreqSpinner = (Spinner) mView.findViewById(R.id.freqSpinner);
mFreqSpinner.setOnItemSelectedListener(this);
ArrayAdapter freqAdapter = ArrayAdapter.createFromResource(getActivity(),
R.array.recurrence_freq, R.layout.recurrencepicker_freq_item);
freqAdapter.setDropDownViewResource(R.layout.recurrencepicker_freq_item);
mFreqSpinner.setAdapter(freqAdapter);
mInterval = (EditText) mView.findViewById(R.id.interval);
mInterval.addTextChangedListener(new minMaxTextWatcher(1, INTERVAL_DEFAULT, INTERVAL_MAX) {
@Override
void onChange(int v) {
if (mIntervalResId != -1 && mInterval.getText().toString().length() > 0) {
mModel.interval = v;
updateIntervalText();
mInterval.requestLayout();
}
}
});
mIntervalPreText = (TextView) mView.findViewById(R.id.intervalPreText);
mIntervalPostText = (TextView) mView.findViewById(R.id.intervalPostText);
mEndNeverStr = mResources.getString(R.string.recurrence_end_continously);
mEndDateLabel = mResources.getString(R.string.recurrence_end_date_label);
mEndCountLabel = mResources.getString(R.string.recurrence_end_count_label);
mEndSpinnerArray.add(mEndNeverStr);
mEndSpinnerArray.add(mEndDateLabel);
mEndSpinnerArray.add(mEndCountLabel);
mEndSpinner = (Spinner) mView.findViewById(R.id.endSpinner);
mEndSpinner.setOnItemSelectedListener(this);
mEndSpinnerAdapter = new EndSpinnerAdapter(getActivity(), mEndSpinnerArray,
R.layout.recurrencepicker_freq_item, R.layout.recurrencepicker_end_text);
mEndSpinnerAdapter.setDropDownViewResource(R.layout.recurrencepicker_freq_item);
mEndSpinner.setAdapter(mEndSpinnerAdapter);
mEndCount = (EditText) mView.findViewById(R.id.endCount);
mEndCount.addTextChangedListener(new minMaxTextWatcher(1, COUNT_DEFAULT, COUNT_MAX) {
@Override
void onChange(int v) {
if (mModel.endCount != v) {
mModel.endCount = v;
updateEndCountText();
mEndCount.requestLayout();
}
}
});
mPostEndCount = (TextView) mView.findViewById(R.id.postEndCount);
mEndDateTextView = (TextView) mView.findViewById(R.id.endDate);
mEndDateTextView.setOnClickListener(this);
if (mModel.endDate == null) {
mModel.endDate = new Time(mTime);
switch (mModel.freq) {
case RecurrenceModel.FREQ_DAILY:
case RecurrenceModel.FREQ_WEEKLY:
mModel.endDate.month += 1;
break;
case RecurrenceModel.FREQ_MONTHLY:
mModel.endDate.month += 3;
break;
case RecurrenceModel.FREQ_YEARLY:
mModel.endDate.year += 3;
break;
}
mModel.endDate.normalize(false);
}
mWeekGroup = (LinearLayout) mView.findViewById(R.id.weekGroup);
mWeekGroup2 = (LinearLayout) mView.findViewById(R.id.weekGroup2);
// In Calendar.java day of week order e.g Sun = 1 ... Sat = 7
String[] dayOfWeekString = new DateFormatSymbols().getWeekdays();
mMonthRepeatByDayOfWeekStrs = new String[7][];
// from Time.SUNDAY as 0 through Time.SATURDAY as 6
mMonthRepeatByDayOfWeekStrs[0] = mResources.getStringArray(R.array.repeat_by_nth_sun);
mMonthRepeatByDayOfWeekStrs[1] = mResources.getStringArray(R.array.repeat_by_nth_mon);
mMonthRepeatByDayOfWeekStrs[2] = mResources.getStringArray(R.array.repeat_by_nth_tues);
mMonthRepeatByDayOfWeekStrs[3] = mResources.getStringArray(R.array.repeat_by_nth_wed);
mMonthRepeatByDayOfWeekStrs[4] = mResources.getStringArray(R.array.repeat_by_nth_thurs);
mMonthRepeatByDayOfWeekStrs[5] = mResources.getStringArray(R.array.repeat_by_nth_fri);
mMonthRepeatByDayOfWeekStrs[6] = mResources.getStringArray(R.array.repeat_by_nth_sat);
// In Time.java day of week order e.g. Sun = 0
int idx = Utils.getFirstDayOfWeek(getActivity());
// In Calendar.java day of week order e.g Sun = 1 ... Sat = 7
dayOfWeekString = new DateFormatSymbols().getShortWeekdays();
int numOfButtonsInRow1;
int numOfButtonsInRow2;
if (mResources.getConfiguration().screenWidthDp > MIN_SCREEN_WIDTH_FOR_SINGLE_ROW_WEEK) {
numOfButtonsInRow1 = 7;
numOfButtonsInRow2 = 0;
mWeekGroup2.setVisibility(View.GONE);
mWeekGroup2.getChildAt(3).setVisibility(View.GONE);
} else {
numOfButtonsInRow1 = 4;
numOfButtonsInRow2 = 3;
mWeekGroup2.setVisibility(View.VISIBLE);
// Set rightmost button on the second row invisible so it takes up
// space and everything centers properly
mWeekGroup2.getChildAt(3).setVisibility(View.INVISIBLE);
}
/* First row */
for (int i = 0; i < 7; i++) {
if (i >= numOfButtonsInRow1) {
mWeekGroup.getChildAt(i).setVisibility(View.GONE);
continue;
}
mWeekByDayButtons[idx] = (ToggleButton) mWeekGroup.getChildAt(i);
mWeekByDayButtons[idx].setTextOff(dayOfWeekString[TIME_DAY_TO_CALENDAR_DAY[idx]]);
mWeekByDayButtons[idx].setTextOn(dayOfWeekString[TIME_DAY_TO_CALENDAR_DAY[idx]]);
mWeekByDayButtons[idx].setOnCheckedChangeListener(this);
if (++idx >= 7) {
idx = 0;
}
}
/* 2nd Row */
for (int i = 0; i < 3; i++) {
if (i >= numOfButtonsInRow2) {
mWeekGroup2.getChildAt(i).setVisibility(View.GONE);
continue;
}
mWeekByDayButtons[idx] = (ToggleButton) mWeekGroup2.getChildAt(i);
mWeekByDayButtons[idx].setTextOff(dayOfWeekString[TIME_DAY_TO_CALENDAR_DAY[idx]]);
mWeekByDayButtons[idx].setTextOn(dayOfWeekString[TIME_DAY_TO_CALENDAR_DAY[idx]]);
mWeekByDayButtons[idx].setOnCheckedChangeListener(this);
if (++idx >= 7) {
idx = 0;
}
}
mMonthGroup = (LinearLayout) mView.findViewById(R.id.monthGroup);
mMonthRepeatByRadioGroup = (RadioGroup) mView.findViewById(R.id.monthGroup);
mMonthRepeatByRadioGroup.setOnCheckedChangeListener(this);
mRepeatMonthlyByNthDayOfWeek = (RadioButton) mView
.findViewById(R.id.repeatMonthlyByNthDayOfTheWeek);
mRepeatMonthlyByNthDayOfMonth = (RadioButton) mView
.findViewById(R.id.repeatMonthlyByNthDayOfMonth);
mDone = (Button) mView.findViewById(R.id.done);
mDone.setOnClickListener(this);
togglePickerOptions();
updateDialog();
if (endCountHasFocus) {
mEndCount.requestFocus();
}
return mView;
}
private void togglePickerOptions() {
if (mModel.recurrenceState == RecurrenceModel.STATE_NO_RECURRENCE) {
mFreqSpinner.setEnabled(false);
mEndSpinner.setEnabled(false);
mIntervalPreText.setEnabled(false);
mInterval.setEnabled(false);
mIntervalPostText.setEnabled(false);
mMonthRepeatByRadioGroup.setEnabled(false);
mEndCount.setEnabled(false);
mPostEndCount.setEnabled(false);
mEndDateTextView.setEnabled(false);
mRepeatMonthlyByNthDayOfWeek.setEnabled(false);
mRepeatMonthlyByNthDayOfMonth.setEnabled(false);
for (Button button : mWeekByDayButtons) {
button.setEnabled(false);
}
} else {
mView.findViewById(R.id.options).setEnabled(true);
mFreqSpinner.setEnabled(true);
mEndSpinner.setEnabled(true);
mIntervalPreText.setEnabled(true);
mInterval.setEnabled(true);
mIntervalPostText.setEnabled(true);
mMonthRepeatByRadioGroup.setEnabled(true);
mEndCount.setEnabled(true);
mPostEndCount.setEnabled(true);
mEndDateTextView.setEnabled(true);
mRepeatMonthlyByNthDayOfWeek.setEnabled(true);
mRepeatMonthlyByNthDayOfMonth.setEnabled(true);
for (Button button : mWeekByDayButtons) {
button.setEnabled(true);
}
}
updateDoneButtonState();
}
private void updateDoneButtonState() {
if (mModel.recurrenceState == RecurrenceModel.STATE_NO_RECURRENCE) {
mDone.setEnabled(true);
return;
}
if (mInterval.getText().toString().length() == 0) {
mDone.setEnabled(false);
return;
}
if (mEndCount.getVisibility() == View.VISIBLE &&
mEndCount.getText().toString().length() == 0) {
mDone.setEnabled(false);
return;
}
if (mModel.freq == RecurrenceModel.FREQ_WEEKLY) {
for (CompoundButton b : mWeekByDayButtons) {
if (b.isChecked()) {
mDone.setEnabled(true);
return;
}
}
mDone.setEnabled(false);
return;
}
mDone.setEnabled(true);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(BUNDLE_MODEL, mModel);
if (mEndCount.hasFocus()) {
outState.putBoolean(BUNDLE_END_COUNT_HAS_FOCUS, true);
}
}
public void updateDialog() {
// Interval
// Checking before setting because this causes infinite recursion
// in afterTextWatcher
final String intervalStr = Integer.toString(mModel.interval);
if (!intervalStr.equals(mInterval.getText().toString())) {
mInterval.setText(intervalStr);
}
mFreqSpinner.setSelection(mModel.freq);
mWeekGroup.setVisibility(mModel.freq == RecurrenceModel.FREQ_WEEKLY ? View.VISIBLE : View.GONE);
mWeekGroup2.setVisibility(mModel.freq == RecurrenceModel.FREQ_WEEKLY ? View.VISIBLE : View.GONE);
mMonthGroup.setVisibility(mModel.freq == RecurrenceModel.FREQ_MONTHLY ? View.VISIBLE : View.GONE);
switch (mModel.freq) {
case RecurrenceModel.FREQ_DAILY:
mIntervalResId = R.plurals.recurrence_interval_daily;
break;
case RecurrenceModel.FREQ_WEEKLY:
mIntervalResId = R.plurals.recurrence_interval_weekly;
for (int i = 0; i < 7; i++) {
mWeekByDayButtons[i].setChecked(mModel.weeklyByDayOfWeek[i]);
}
break;
case RecurrenceModel.FREQ_MONTHLY:
mIntervalResId = R.plurals.recurrence_interval_monthly;
if (mModel.monthlyRepeat == RecurrenceModel.MONTHLY_BY_DATE) {
mMonthRepeatByRadioGroup.check(R.id.repeatMonthlyByNthDayOfMonth);
} else if (mModel.monthlyRepeat == RecurrenceModel.MONTHLY_BY_NTH_DAY_OF_WEEK) {
mMonthRepeatByRadioGroup.check(R.id.repeatMonthlyByNthDayOfTheWeek);
}
if (mMonthRepeatByDayOfWeekStr == null) {
if (mModel.monthlyByNthDayOfWeek == 0) {
mModel.monthlyByNthDayOfWeek = (mTime.monthDay + 6) / 7;
// Since not all months have 5 weeks, we convert 5th NthDayOfWeek to
// -1 for last monthly day of the week
if (mModel.monthlyByNthDayOfWeek >= FIFTH_WEEK_IN_A_MONTH) {
mModel.monthlyByNthDayOfWeek = LAST_NTH_DAY_OF_WEEK;
}
mModel.monthlyByDayOfWeek = mTime.weekDay;
}
String[] monthlyByNthDayOfWeekStrs =
mMonthRepeatByDayOfWeekStrs[mModel.monthlyByDayOfWeek];
// TODO(psliwowski): Find a better way handle -1 indexes
int msgIndex = mModel.monthlyByNthDayOfWeek < 0 ? FIFTH_WEEK_IN_A_MONTH :
mModel.monthlyByNthDayOfWeek;
mMonthRepeatByDayOfWeekStr =
monthlyByNthDayOfWeekStrs[msgIndex - 1];
mRepeatMonthlyByNthDayOfWeek.setText(mMonthRepeatByDayOfWeekStr);
}
break;
case RecurrenceModel.FREQ_YEARLY:
mIntervalResId = R.plurals.recurrence_interval_yearly;
break;
}
updateIntervalText();
updateDoneButtonState();
mEndSpinner.setSelection(mModel.end);
if (mModel.end == RecurrenceModel.END_BY_DATE) {
final String dateStr = DateUtils.formatDateTime(getActivity(),
mModel.endDate.toMillis(false), DateUtils.FORMAT_NUMERIC_DATE);
mEndDateTextView.setText(dateStr);
} else {
if (mModel.end == RecurrenceModel.END_BY_COUNT) {
// Checking before setting because this causes infinite
// recursion
// in afterTextWatcher
final String countStr = Integer.toString(mModel.endCount);
if (!countStr.equals(mEndCount.getText().toString())) {
mEndCount.setText(countStr);
}
}
}
}
/**
* @param endDateString
*/
private void setEndSpinnerEndDateStr(final String endDateString) {
mEndSpinnerArray.set(1, endDateString);
mEndSpinnerAdapter.notifyDataSetChanged();
}
private void doToast() {
Log.e(TAG, "Model = " + mModel.toString());
String rrule;
if (mModel.recurrenceState == RecurrenceModel.STATE_NO_RECURRENCE) {
rrule = "Not repeating";
} else {
copyModelToEventRecurrence(mModel, mRecurrence);
rrule = mRecurrence.toString();
}
if (mToast != null) {
mToast.cancel();
}
mToast = Toast.makeText(getActivity(), rrule,
Toast.LENGTH_LONG);
mToast.show();
}
// TODO Test and update for Right-to-Left
private void updateIntervalText() {
if (mIntervalResId == -1) {
return;
}
final String INTERVAL_COUNT_MARKER = "%d";
String intervalString = mResources.getQuantityString(mIntervalResId, mModel.interval);
int markerStart = intervalString.indexOf(INTERVAL_COUNT_MARKER);
if (markerStart != -1) {
int postTextStart = markerStart + INTERVAL_COUNT_MARKER.length();
mIntervalPostText.setText(intervalString.substring(postTextStart,
intervalString.length()).trim());
mIntervalPreText.setText(intervalString.substring(0, markerStart).trim());
}
}
/**
* Update the "Repeat for N events" end option with the proper string values
* based on the value that has been entered for N.
*/
private void updateEndCountText() {
final String END_COUNT_MARKER = "%d";
String endString = mResources.getQuantityString(R.plurals.recurrence_end_count,
mModel.endCount);
int markerStart = endString.indexOf(END_COUNT_MARKER);
if (markerStart != -1) {
if (markerStart == 0) {
Log.e(TAG, "No text to put in to recurrence's end spinner.");
} else {
int postTextStart = markerStart + END_COUNT_MARKER.length();
mPostEndCount.setText(endString.substring(postTextStart,
endString.length()).trim());
}
}
}
// Implements OnItemSelectedListener interface
// Freq spinner
// End spinner
@Override
public void onItemSelected(AdapterView> parent, View view, int position, long id) {
if (parent == mFreqSpinner) {
mModel.freq = position;
} else if (parent == mEndSpinner) {
switch (position) {
case RecurrenceModel.END_NEVER:
mModel.end = RecurrenceModel.END_NEVER;
break;
case RecurrenceModel.END_BY_DATE:
mModel.end = RecurrenceModel.END_BY_DATE;
break;
case RecurrenceModel.END_BY_COUNT:
mModel.end = RecurrenceModel.END_BY_COUNT;
if (mModel.endCount <= 1) {
mModel.endCount = 1;
} else if (mModel.endCount > COUNT_MAX) {
mModel.endCount = COUNT_MAX;
}
updateEndCountText();
break;
}
mEndCount.setVisibility(mModel.end == RecurrenceModel.END_BY_COUNT ? View.VISIBLE
: View.GONE);
mEndDateTextView.setVisibility(mModel.end == RecurrenceModel.END_BY_DATE ? View.VISIBLE
: View.GONE);
mPostEndCount.setVisibility(
mModel.end == RecurrenceModel.END_BY_COUNT && !mHidePostEndCount ?
View.VISIBLE : View.GONE);
}
updateDialog();
}
// Implements OnItemSelectedListener interface
@Override
public void onNothingSelected(AdapterView> arg0) {
}
@Override
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
if (mModel.endDate == null) {
mModel.endDate = new Time(mTime.timezone);
mModel.endDate.hour = mModel.endDate.minute = mModel.endDate.second = 0;
}
mModel.endDate.year = year;
mModel.endDate.month = monthOfYear;
mModel.endDate.monthDay = dayOfMonth;
mModel.endDate.normalize(false);
updateDialog();
}
// Implements OnCheckedChangeListener interface
// Week repeat by day of week
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int itemIdx = -1;
for (int i = 0; i < 7; i++) {
if (itemIdx == -1 && buttonView == mWeekByDayButtons[i]) {
itemIdx = i;
mModel.weeklyByDayOfWeek[i] = isChecked;
}
}
updateDialog();
}
// Implements android.widget.RadioGroup.OnCheckedChangeListener interface
// Month repeat by radio buttons
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == R.id.repeatMonthlyByNthDayOfMonth) {
mModel.monthlyRepeat = RecurrenceModel.MONTHLY_BY_DATE;
} else if (checkedId == R.id.repeatMonthlyByNthDayOfTheWeek) {
mModel.monthlyRepeat = RecurrenceModel.MONTHLY_BY_NTH_DAY_OF_WEEK;
}
updateDialog();
}
// Implements OnClickListener interface
// EndDate button
// Done button
@Override
public void onClick(View v) {
if (mEndDateTextView == v) {
if (mDatePickerDialog != null) {
mDatePickerDialog.dismiss();
}
mDatePickerDialog = DatePickerDialog.newInstance(this, mModel.endDate.year,
mModel.endDate.month, mModel.endDate.monthDay);
mDatePickerDialog.setFirstDayOfWeek(Utils.getFirstDayOfWeekAsCalendar(getActivity()));
mDatePickerDialog.setYearRange(Utils.YEAR_MIN, Utils.YEAR_MAX);
mDatePickerDialog.show(getFragmentManager(), FRAG_TAG_DATE_PICKER);
} else if (mDone == v) {
String rrule;
if (mModel.recurrenceState == RecurrenceModel.STATE_NO_RECURRENCE) {
rrule = null;
} else {
copyModelToEventRecurrence(mModel, mRecurrence);
rrule = mRecurrence.toString();
}
if (mRecurrenceSetListener != null) {
mRecurrenceSetListener.onRecurrenceSet(rrule);
}
dismiss();
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mDatePickerDialog = (DatePickerDialog) getFragmentManager()
.findFragmentByTag(FRAG_TAG_DATE_PICKER);
if (mDatePickerDialog != null) {
mDatePickerDialog.setOnDateSetListener(this);
}
}
public interface OnRecurrenceSetListener {
void onRecurrenceSet(String rrule);
}
public void setOnRecurrenceSetListener(OnRecurrenceSetListener l) {
mRecurrenceSetListener = l;
}
private class EndSpinnerAdapter extends ArrayAdapter {
final String END_DATE_MARKER = "%s";
final String END_COUNT_MARKER = "%d";
private LayoutInflater mInflater;
private int mItemResourceId;
private int mTextResourceId;
private ArrayList mStrings;
private String mEndDateString;
private boolean mUseFormStrings;
/**
* @param context
* @param textViewResourceId
* @param objects
*/
public EndSpinnerAdapter(Context context, ArrayList strings,
int itemResourceId, int textResourceId) {
super(context, itemResourceId, strings);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mItemResourceId = itemResourceId;
mTextResourceId = textResourceId;
mStrings = strings;
mEndDateString = getResources().getString(R.string.recurrence_end_date);
// If either date or count strings don't translate well, such that we aren't assured
// to have some text available to be placed in the spinner, then we'll have to use
// the more form-like versions of both strings instead.
int markerStart = mEndDateString.indexOf(END_DATE_MARKER);
if (markerStart <= 0) {
// The date string does not have any text before the "%s" so we'll have to use the
// more form-like strings instead.
mUseFormStrings = true;
} else {
String countEndStr = getResources().getQuantityString(
R.plurals.recurrence_end_count, 1);
markerStart = countEndStr.indexOf(END_COUNT_MARKER);
if (markerStart <= 0) {
// The count string does not have any text before the "%d" so we'll have to use
// the more form-like strings instead.
mUseFormStrings = true;
}
}
if (mUseFormStrings) {
// We'll have to set the layout for the spinner to be weight=0 so it doesn't
// take up too much space.
mEndSpinner.setLayoutParams(
new TableLayout.LayoutParams(0, LayoutParams.WRAP_CONTENT, 1f));
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v;
// Check if we can recycle the view
if (convertView == null) {
v = mInflater.inflate(mTextResourceId, parent, false);
} else {
v = convertView;
}
TextView item = (TextView) v.findViewById(R.id.spinner_item);
int markerStart;
switch (position) {
case RecurrenceModel.END_NEVER:
item.setText(mStrings.get(RecurrenceModel.END_NEVER));
break;
case RecurrenceModel.END_BY_DATE:
markerStart = mEndDateString.indexOf(END_DATE_MARKER);
if (markerStart != -1) {
if (mUseFormStrings || markerStart == 0) {
// If we get here, the translation of "Until" doesn't work correctly,
// so we'll just set the whole "Until a date" string.
item.setText(mEndDateLabel);
} else {
item.setText(mEndDateString.substring(0, markerStart).trim());
}
}
break;
case RecurrenceModel.END_BY_COUNT:
String endString = mResources.getQuantityString(R.plurals.recurrence_end_count,
mModel.endCount);
markerStart = endString.indexOf(END_COUNT_MARKER);
if (markerStart != -1) {
if (mUseFormStrings || markerStart == 0) {
// If we get here, the translation of "For" doesn't work correctly,
// so we'll just set the whole "For a number of events" string.
item.setText(mEndCountLabel);
// Also, we'll hide the " events" that would have been at the end.
mPostEndCount.setVisibility(View.GONE);
// Use this flag so the onItemSelected knows whether to show it later.
mHidePostEndCount = true;
} else {
int postTextStart = markerStart + END_COUNT_MARKER.length();
mPostEndCount.setText(endString.substring(postTextStart,
endString.length()).trim());
// In case it's a recycled view that wasn't visible.
if (mModel.end == RecurrenceModel.END_BY_COUNT) {
mPostEndCount.setVisibility(View.VISIBLE);
}
if (endString.charAt(markerStart - 1) == ' ') {
markerStart--;
}
item.setText(endString.substring(0, markerStart).trim());
}
}
break;
default:
v = null;
break;
}
return v;
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
View v;
// Check if we can recycle the view
if (convertView == null) {
v = mInflater.inflate(mItemResourceId, parent, false);
} else {
v = convertView;
}
TextView item = (TextView) v.findViewById(R.id.spinner_item);
item.setText(mStrings.get(position));
return v;
}
}
}
================================================
FILE: library/src/main/java/be/billington/calendar/recurrencepicker/Utils.java
================================================
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package be.billington.calendar.recurrencepicker;
import android.accounts.Account;
import android.app.Activity;
import android.app.SearchManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.CalendarContract.Calendars;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.format.Time;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.util.Log;
import android.widget.SearchView;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static android.provider.CalendarContract.EXTRA_EVENT_BEGIN_TIME;
public class Utils {
private static final boolean DEBUG = false;
private static final String TAG = "CalUtils";
// Set to 0 until we have UI to perform undo
public static final long UNDO_DELAY = 0;
// For recurring events which instances of the series are being modified
public static final int MODIFY_UNINITIALIZED = 0;
public static final int MODIFY_SELECTED = 1;
public static final int MODIFY_ALL_FOLLOWING = 2;
public static final int MODIFY_ALL = 3;
// When the edit event view finishes it passes back the appropriate exit
// code.
public static final int DONE_REVERT = 1 << 0;
public static final int DONE_SAVE = 1 << 1;
public static final int DONE_DELETE = 1 << 2;
// And should re run with DONE_EXIT if it should also leave the view, just
// exiting is identical to reverting
public static final int DONE_EXIT = 1 << 0;
public static final String OPEN_EMAIL_MARKER = " <";
public static final String CLOSE_EMAIL_MARKER = ">";
public static final String INTENT_KEY_DETAIL_VIEW = "DETAIL_VIEW";
public static final String INTENT_KEY_VIEW_TYPE = "VIEW";
public static final String INTENT_VALUE_VIEW_TYPE_DAY = "DAY";
public static final String INTENT_KEY_HOME = "KEY_HOME";
public static final int MONDAY_BEFORE_JULIAN_EPOCH = Time.EPOCH_JULIAN_DAY - 3;
public static final int DECLINED_EVENT_ALPHA = 0x66;
public static final int DECLINED_EVENT_TEXT_ALPHA = 0xC0;
private static final float SATURATION_ADJUST = 1.3f;
private static final float INTENSITY_ADJUST = 0.8f;
// Defines used by the DNA generation code
static final int DAY_IN_MINUTES = 60 * 24;
static final int WEEK_IN_MINUTES = DAY_IN_MINUTES * 7;
// The work day is being counted as 6am to 8pm
static int WORK_DAY_MINUTES = 14 * 60;
static int WORK_DAY_START_MINUTES = 6 * 60;
static int WORK_DAY_END_MINUTES = 20 * 60;
static int WORK_DAY_END_LENGTH = (24 * 60) - WORK_DAY_END_MINUTES;
static int CONFLICT_COLOR = 0xFF000000;
static boolean mMinutesLoaded = false;
public static final int YEAR_MIN = 1970;
public static final int YEAR_MAX = 2036;
// The name of the shared preferences file. This name must be maintained for
// historical
// reasons, as it's what PreferenceManager assigned the first time the file
// was created.
static final String SHARED_PREFS_NAME = "com.android.calendar_preferences";
public static final String KEY_QUICK_RESPONSES = "preferences_quick_responses";
public static final String KEY_ALERTS_VIBRATE_WHEN = "preferences_alerts_vibrateWhen";
public static final String APPWIDGET_DATA_TYPE = "vnd.android.data/update";
static final String MACHINE_GENERATED_ADDRESS = "calendar.google.com";
private static boolean mAllowWeekForDetailView = false;
private static long mTardis = 0;
private static String sVersion = null;
private static final Pattern mWildcardPattern = Pattern.compile("^.*$");
/**
* A coordinate must be of the following form for Google Maps to correctly use it:
* Latitude, Longitude
*
* This may be in decimal form:
* Latitude: {-90 to 90}
* Longitude: {-180 to 180}
*
* Or, in degrees, minutes, and seconds:
* Latitude: {-90 to 90}° {0 to 59}' {0 to 59}"
* Latitude: {-180 to 180}° {0 to 59}' {0 to 59}"
* + or - degrees may also be represented with N or n, S or s for latitude, and with
* E or e, W or w for longitude, where the direction may either precede or follow the value.
*
* Some examples of coordinates that will be accepted by the regex:
* 37.422081°, -122.084576°
* 37.422081,-122.084576
* +37°25'19.49", -122°5'4.47"
* 37°25'19.49"N, 122°5'4.47"W
* N 37° 25' 19.49", W 122° 5' 4.47"
*/
private static final String COORD_DEGREES_LATITUDE =
"([-+NnSs]" + "(\\s)*)?"
+ "[1-9]?[0-9](\u00B0)" + "(\\s)*"
+ "([1-5]?[0-9]\')?" + "(\\s)*"
+ "([1-5]?[0-9]" + "(\\.[0-9]+)?\")?"
+ "((\\s)*" + "[NnSs])?";
private static final String COORD_DEGREES_LONGITUDE =
"([-+EeWw]" + "(\\s)*)?"
+ "(1)?[0-9]?[0-9](\u00B0)" + "(\\s)*"
+ "([1-5]?[0-9]\')?" + "(\\s)*"
+ "([1-5]?[0-9]" + "(\\.[0-9]+)?\")?"
+ "((\\s)*" + "[EeWw])?";
private static final String COORD_DEGREES_PATTERN =
COORD_DEGREES_LATITUDE
+ "(\\s)*" + "," + "(\\s)*"
+ COORD_DEGREES_LONGITUDE;
private static final String COORD_DECIMAL_LATITUDE =
"[+-]?"
+ "[1-9]?[0-9]" + "(\\.[0-9]+)"
+ "(\u00B0)?";
private static final String COORD_DECIMAL_LONGITUDE =
"[+-]?"
+ "(1)?[0-9]?[0-9]" + "(\\.[0-9]+)"
+ "(\u00B0)?";
private static final String COORD_DECIMAL_PATTERN =
COORD_DECIMAL_LATITUDE
+ "(\\s)*" + "," + "(\\s)*"
+ COORD_DECIMAL_LONGITUDE;
private static final Pattern COORD_PATTERN =
Pattern.compile(COORD_DEGREES_PATTERN + "|" + COORD_DECIMAL_PATTERN);
private static final String NANP_ALLOWED_SYMBOLS = "()+-*#.";
private static final int NANP_MIN_DIGITS = 7;
private static final int NANP_MAX_DIGITS = 11;
/**
* Returns whether the SDK is the Jellybean release or later.
*/
public static boolean isJellybeanOrLater() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
}
/**
* Returns whether the SDK is the KeyLimePie release or later.
*/
public static boolean isKeyLimePieOrLater() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
}
/**
* Gets the intent action for telling the widget to update.
*/
public static String getWidgetUpdateAction(Context context) {
return context.getPackageName() + ".APPWIDGET_UPDATE";
}
/**
* Gets the intent action for telling the widget to update.
*/
public static String getWidgetScheduledUpdateAction(Context context) {
return context.getPackageName() + ".APPWIDGET_SCHEDULED_UPDATE";
}
/**
* Gets the intent action for telling the widget to update.
*/
public static String getSearchAuthority(Context context) {
return context.getPackageName() + ".CalendarRecentSuggestionsProvider";
}
protected static void tardis() {
mTardis = System.currentTimeMillis();
}
protected static long getTardis() {
return mTardis;
}
public static MatrixCursor matrixCursorFromCursor(Cursor cursor) {
if (cursor == null) {
return null;
}
String[] columnNames = cursor.getColumnNames();
if (columnNames == null) {
columnNames = new String[]{};
}
MatrixCursor newCursor = new MatrixCursor(columnNames);
int numColumns = cursor.getColumnCount();
String data[] = new String[numColumns];
cursor.moveToPosition(-1);
while (cursor.moveToNext()) {
for (int i = 0; i < numColumns; i++) {
data[i] = cursor.getString(i);
}
newCursor.addRow(data);
}
return newCursor;
}
/**
* Compares two cursors to see if they contain the same data.
*
* @return Returns true of the cursors contain the same data and are not
* null, false otherwise
*/
public static boolean compareCursors(Cursor c1, Cursor c2) {
if (c1 == null || c2 == null) {
return false;
}
int numColumns = c1.getColumnCount();
if (numColumns != c2.getColumnCount()) {
return false;
}
if (c1.getCount() != c2.getCount()) {
return false;
}
c1.moveToPosition(-1);
c2.moveToPosition(-1);
while (c1.moveToNext() && c2.moveToNext()) {
for (int i = 0; i < numColumns; i++) {
if (!TextUtils.equals(c1.getString(i), c2.getString(i))) {
return false;
}
}
}
return true;
}
/**
* If the given intent specifies a time (in milliseconds since the epoch),
* then that time is returned. Otherwise, the current time is returned.
*/
public static final long timeFromIntentInMillis(Intent intent) {
// If the time was specified, then use that. Otherwise, use the current
// time.
Uri data = intent.getData();
long millis = intent.getLongExtra(EXTRA_EVENT_BEGIN_TIME, -1);
if (millis == -1 && data != null && data.isHierarchical()) {
List path = data.getPathSegments();
if (path.size() == 2 && path.get(0).equals("time")) {
try {
millis = Long.valueOf(data.getLastPathSegment());
} catch (NumberFormatException e) {
Log.i("Calendar", "timeFromIntentInMillis: Data existed but no valid time "
+ "found. Using current time.");
}
}
}
if (millis <= 0) {
millis = System.currentTimeMillis();
}
return millis;
}
/**
* Returns a list joined together by the provided delimiter, for example,
* ["a", "b", "c"] could be joined into "a,b,c"
*
* @param things the things to join together
* @param delim the delimiter to use
* @return a string contained the things joined together
*/
public static String join(List> things, String delim) {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (Object thing : things) {
if (first) {
first = false;
} else {
builder.append(delim);
}
builder.append(thing.toString());
}
return builder.toString();
}
/**
* Returns the week since {@link android.text.format.Time#EPOCH_JULIAN_DAY} (Jan 1, 1970)
* adjusted for first day of week.
*
* This takes a julian day and the week start day and calculates which
* week since {@link android.text.format.Time#EPOCH_JULIAN_DAY} that day occurs in, starting
* at 0. *Do not* use this to compute the ISO week number for the year.
*
* @param julianDay The julian day to calculate the week number for
* @param firstDayOfWeek Which week day is the first day of the week,
* see {@link android.text.format.Time#SUNDAY}
* @return Weeks since the epoch
*/
public static int getWeeksSinceEpochFromJulianDay(int julianDay, int firstDayOfWeek) {
int diff = Time.THURSDAY - firstDayOfWeek;
if (diff < 0) {
diff += 7;
}
int refDay = Time.EPOCH_JULIAN_DAY - diff;
return (julianDay - refDay) / 7;
}
/**
* Takes a number of weeks since the epoch and calculates the Julian day of
* the Monday for that week.
*
* This assumes that the week containing the {@link android.text.format.Time#EPOCH_JULIAN_DAY}
* is considered week 0. It returns the Julian day for the Monday
* {@code week} weeks after the Monday of the week containing the epoch.
*
* @param week Number of weeks since the epoch
* @return The julian day for the Monday of the given week since the epoch
*/
public static int getJulianMondayFromWeeksSinceEpoch(int week) {
return MONDAY_BEFORE_JULIAN_EPOCH + week * 7;
}
/**
* Get first day of week as android.text.format.Time constant.
*
* @return the first day of week in android.text.format.Time
*/
public static int getFirstDayOfWeek(Context context) {
int startDay = Calendar.getInstance().getFirstDayOfWeek();
if (startDay == Calendar.SATURDAY) {
return Time.SATURDAY;
} else if (startDay == Calendar.MONDAY) {
return Time.MONDAY;
} else {
return Time.SUNDAY;
}
}
/**
* Get first day of week as java.util.Calendar constant.
*
* @return the first day of week as a java.util.Calendar constant
*/
public static int getFirstDayOfWeekAsCalendar(Context context) {
return convertDayOfWeekFromTimeToCalendar(getFirstDayOfWeek(context));
}
/**
* Converts the day of the week from android.text.format.Time to java.util.Calendar
*/
public static int convertDayOfWeekFromTimeToCalendar(int timeDayOfWeek) {
switch (timeDayOfWeek) {
case Time.MONDAY:
return Calendar.MONDAY;
case Time.TUESDAY:
return Calendar.TUESDAY;
case Time.WEDNESDAY:
return Calendar.WEDNESDAY;
case Time.THURSDAY:
return Calendar.THURSDAY;
case Time.FRIDAY:
return Calendar.FRIDAY;
case Time.SATURDAY:
return Calendar.SATURDAY;
case Time.SUNDAY:
return Calendar.SUNDAY;
default:
throw new IllegalArgumentException("Argument must be between Time.SUNDAY and " +
"Time.SATURDAY");
}
}
/**
* Determine whether the column position is Saturday or not.
*
* @param column the column position
* @param firstDayOfWeek the first day of week in android.text.format.Time
* @return true if the column is Saturday position
*/
public static boolean isSaturday(int column, int firstDayOfWeek) {
return (firstDayOfWeek == Time.SUNDAY && column == 6)
|| (firstDayOfWeek == Time.MONDAY && column == 5)
|| (firstDayOfWeek == Time.SATURDAY && column == 0);
}
/**
* Determine whether the column position is Sunday or not.
*
* @param column the column position
* @param firstDayOfWeek the first day of week in android.text.format.Time
* @return true if the column is Sunday position
*/
public static boolean isSunday(int column, int firstDayOfWeek) {
return (firstDayOfWeek == Time.SUNDAY && column == 0)
|| (firstDayOfWeek == Time.MONDAY && column == 6)
|| (firstDayOfWeek == Time.SATURDAY && column == 1);
}
/**
* Convert given UTC time into current local time. This assumes it is for an
* allday event and will adjust the time to be on a midnight boundary.
*
* @param recycle Time object to recycle, otherwise null.
* @param utcTime Time to convert, in UTC.
* @param tz The time zone to convert this time to.
*/
public static long convertAlldayUtcToLocal(Time recycle, long utcTime, String tz) {
if (recycle == null) {
recycle = new Time();
}
recycle.timezone = Time.TIMEZONE_UTC;
recycle.set(utcTime);
recycle.timezone = tz;
return recycle.normalize(true);
}
public static long convertAlldayLocalToUTC(Time recycle, long localTime, String tz) {
if (recycle == null) {
recycle = new Time();
}
recycle.timezone = tz;
recycle.set(localTime);
recycle.timezone = Time.TIMEZONE_UTC;
return recycle.normalize(true);
}
/**
* Finds and returns the next midnight after "theTime" in milliseconds UTC
*
* @param recycle - Time object to recycle, otherwise null.
* @param theTime - Time used for calculations (in UTC)
* @param tz The time zone to convert this time to.
*/
public static long getNextMidnight(Time recycle, long theTime, String tz) {
if (recycle == null) {
recycle = new Time();
}
recycle.timezone = tz;
recycle.set(theTime);
recycle.monthDay++;
recycle.hour = 0;
recycle.minute = 0;
recycle.second = 0;
return recycle.normalize(true);
}
/**
* Scan through a cursor of calendars and check if names are duplicated.
* This travels a cursor containing calendar display names and fills in the
* provided map with whether or not each name is repeated.
*
* @param isDuplicateName The map to put the duplicate check results in.
* @param cursor The query of calendars to check
* @param nameIndex The column of the query that contains the display name
*/
public static void checkForDuplicateNames(
Map isDuplicateName, Cursor cursor, int nameIndex) {
isDuplicateName.clear();
cursor.moveToPosition(-1);
while (cursor.moveToNext()) {
String displayName = cursor.getString(nameIndex);
// Set it to true if we've seen this name before, false otherwise
if (displayName != null) {
isDuplicateName.put(displayName, isDuplicateName.containsKey(displayName));
}
}
}
/**
* Null-safe object comparison
*
* @param s1
* @param s2
* @return
*/
public static boolean equals(Object o1, Object o2) {
return o1 == null ? o2 == null : o1.equals(o2);
}
public static void setAllowWeekForDetailView(boolean allowWeekView) {
mAllowWeekForDetailView = allowWeekView;
}
public static boolean getAllowWeekForDetailView() {
return mAllowWeekForDetailView;
}
public static boolean getConfigBool(Context c, int key) {
return c.getResources().getBoolean(key);
}
/**
* For devices with Jellybean or later, darkens the given color to ensure that white text is
* clearly visible on top of it. For devices prior to Jellybean, does nothing, as the
* sync adapter handles the color change.
*
* @param color
*/
public static int getDisplayColorFromColor(int color) {
if (!isJellybeanOrLater()) {
return color;
}
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[1] = Math.min(hsv[1] * SATURATION_ADJUST, 1.0f);
hsv[2] = hsv[2] * INTENSITY_ADJUST;
return Color.HSVToColor(hsv);
}
// This takes a color and computes what it would look like blended with
// white. The result is the color that should be used for declined events.
public static int getDeclinedColorFromColor(int color) {
int bg = 0xffffffff;
int a = DECLINED_EVENT_ALPHA;
int r = (((color & 0x00ff0000) * a) + ((bg & 0x00ff0000) * (0xff - a))) & 0xff000000;
int g = (((color & 0x0000ff00) * a) + ((bg & 0x0000ff00) * (0xff - a))) & 0x00ff0000;
int b = (((color & 0x000000ff) * a) + ((bg & 0x000000ff) * (0xff - a))) & 0x0000ff00;
return (0xff000000) | ((r | g | b) >> 8);
}
// A single strand represents one color of events. Events are divided up by
// color to make them convenient to draw. The black strand is special in
// that it holds conflicting events as well as color settings for allday on
// each day.
public static class DNAStrand {
public float[] points;
public int[] allDays; // color for the allday, 0 means no event
int position;
public int color;
int count;
}
// A segment is a single continuous length of time occupied by a single
// color. Segments should never span multiple days.
private static class DNASegment {
int startMinute; // in minutes since the start of the week
int endMinute;
int color; // Calendar color or black for conflicts
int day; // quick reference to the day this segment is on
}
// This processes all the segments, sorts them by color, and generates a
// list of points to draw
private static void weaveDNAStrands(LinkedList segments, int firstJulianDay,
HashMap strands, int top, int bottom, int[] dayXs) {
// First, get rid of any colors that ended up with no segments
Iterator strandIterator = strands.values().iterator();
while (strandIterator.hasNext()) {
DNAStrand strand = strandIterator.next();
if (strand.count < 1 && strand.allDays == null) {
strandIterator.remove();
continue;
}
strand.points = new float[strand.count * 4];
strand.position = 0;
}
// Go through each segment and compute its points
for (DNASegment segment : segments) {
// Add the points to the strand of that color
DNAStrand strand = strands.get(segment.color);
int dayIndex = segment.day - firstJulianDay;
int dayStartMinute = segment.startMinute % DAY_IN_MINUTES;
int dayEndMinute = segment.endMinute % DAY_IN_MINUTES;
int height = bottom - top;
int workDayHeight = height * 3 / 4;
int remainderHeight = (height - workDayHeight) / 2;
int x = dayXs[dayIndex];
int y0 = 0;
int y1 = 0;
y0 = top + getPixelOffsetFromMinutes(dayStartMinute, workDayHeight, remainderHeight);
y1 = top + getPixelOffsetFromMinutes(dayEndMinute, workDayHeight, remainderHeight);
if (DEBUG) {
Log.d(TAG, "Adding " + Integer.toHexString(segment.color) + " at x,y0,y1: " + x
+ " " + y0 + " " + y1 + " for " + dayStartMinute + " " + dayEndMinute);
}
strand.points[strand.position++] = x;
strand.points[strand.position++] = y0;
strand.points[strand.position++] = x;
strand.points[strand.position++] = y1;
}
}
/**
* Compute a pixel offset from the top for a given minute from the work day
* height and the height of the top area.
*/
private static int getPixelOffsetFromMinutes(int minute, int workDayHeight,
int remainderHeight) {
int y;
if (minute < WORK_DAY_START_MINUTES) {
y = minute * remainderHeight / WORK_DAY_START_MINUTES;
} else if (minute < WORK_DAY_END_MINUTES) {
y = remainderHeight + (minute - WORK_DAY_START_MINUTES) * workDayHeight
/ WORK_DAY_MINUTES;
} else {
y = remainderHeight + workDayHeight + (minute - WORK_DAY_END_MINUTES) * remainderHeight
/ WORK_DAY_END_LENGTH;
}
return y;
}
/**
* Try to get a strand of the given color. Create it if it doesn't exist.
*/
private static DNAStrand getOrCreateStrand(HashMap strands, int color) {
DNAStrand strand = strands.get(color);
if (strand == null) {
strand = new DNAStrand();
strand.color = color;
strand.count = 0;
strands.put(strand.color, strand);
}
return strand;
}
/**
* This sets up a search view to use Calendar's search suggestions provider
* and to allow refining the search.
*
* @param view The {@link android.widget.SearchView} to set up
* @param act The activity using the view
*/
public static void setUpSearchView(SearchView view, Activity act) {
SearchManager searchManager = (SearchManager) act.getSystemService(Context.SEARCH_SERVICE);
view.setSearchableInfo(searchManager.getSearchableInfo(act.getComponentName()));
view.setQueryRefinementEnabled(true);
}
// Calculate the time until midnight + 1 second and set the handler to
// do run the runnable
public static void setMidnightUpdater(Handler h, Runnable r, String timezone) {
if (h == null || r == null || timezone == null) {
return;
}
long now = System.currentTimeMillis();
Time time = new Time(timezone);
time.set(now);
long runInMillis = (24 * 3600 - time.hour * 3600 - time.minute * 60 -
time.second + 1) * 1000;
h.removeCallbacks(r);
h.postDelayed(r, runInMillis);
}
// Stop the midnight update thread
public static void resetMidnightUpdater(Handler h, Runnable r) {
if (h == null || r == null) {
return;
}
h.removeCallbacks(r);
}
/**
* Returns the timezone to display in the event info, if the local timezone is different
* from the event timezone. Otherwise returns null.
*/
public static String getDisplayedTimezone(long startMillis, String localTimezone,
String eventTimezone) {
String tzDisplay = null;
if (!TextUtils.equals(localTimezone, eventTimezone)) {
// Figure out if this is in DST
TimeZone tz = TimeZone.getTimeZone(localTimezone);
if (tz == null || tz.getID().equals("GMT")) {
tzDisplay = localTimezone;
} else {
Time startTime = new Time(localTimezone);
startTime.set(startMillis);
tzDisplay = tz.getDisplayName(startTime.isDst != 0, TimeZone.SHORT);
}
}
return tzDisplay;
}
/**
* Returns whether the specified time interval is in a single day.
*/
private static boolean singleDayEvent(long startMillis, long endMillis, long localGmtOffset) {
if (startMillis == endMillis) {
return true;
}
// An event ending at midnight should still be a single-day event, so check
// time end-1.
int startDay = Time.getJulianDay(startMillis, localGmtOffset);
int endDay = Time.getJulianDay(endMillis - 1, localGmtOffset);
return startDay == endDay;
}
// Using int constants as a return value instead of an enum to minimize resources.
private static final int TODAY = 1;
private static final int TOMORROW = 2;
private static final int NONE = 0;
/**
* Returns TODAY or TOMORROW if applicable. Otherwise returns NONE.
*/
private static int isTodayOrTomorrow(Resources r, long dayMillis,
long currentMillis, long localGmtOffset) {
int startDay = Time.getJulianDay(dayMillis, localGmtOffset);
int currentDay = Time.getJulianDay(currentMillis, localGmtOffset);
int days = startDay - currentDay;
if (days == 1) {
return TOMORROW;
} else if (days == 0) {
return TODAY;
} else {
return NONE;
}
}
/**
* Create an intent for emailing attendees of an event.
*
* @param resources The resources for translating strings.
* @param eventTitle The title of the event to use as the email subject.
* @param body The default text for the email body.
* @param toEmails The list of emails for the 'to' line.
* @param ccEmails The list of emails for the 'cc' line.
* @param ownerAccount The owner account to use as the email sender.
*/
public static Intent createEmailAttendeesIntent(Resources resources, String eventTitle,
String body, List toEmails, List ccEmails, String ownerAccount) {
List toList = toEmails;
List ccList = ccEmails;
if (toEmails.size() <= 0) {
if (ccEmails.size() <= 0) {
// TODO: Return a SEND intent if no one to email to, to at least populate
// a draft email with the subject (and no recipients).
throw new IllegalArgumentException("Both toEmails and ccEmails are empty.");
}
// Email app does not work with no "to" recipient. Move all 'cc' to 'to'
// in this case.
toList = ccEmails;
ccList = null;
}
// Use the event title as the email subject (prepended with 'Re: ').
String subject = null;
if (eventTitle != null) {
subject = resources.getString(R.string.email_subject_prefix) + eventTitle;
}
// Use the SENDTO intent with a 'mailto' URI, because using SEND will cause
// the picker to show apps like text messaging, which does not make sense
// for email addresses. We put all data in the URI instead of using the extra
// Intent fields (ie. EXTRA_CC, etc) because some email apps might not handle
// those (though gmail does).
Uri.Builder uriBuilder = new Uri.Builder();
uriBuilder.scheme("mailto");
// We will append the first email to the 'mailto' field later (because the
// current state of the Email app requires it). Add the remaining 'to' values
// here. When the email codebase is updated, we can simplify this.
if (toList.size() > 1) {
for (int i = 1; i < toList.size(); i++) {
// The Email app requires repeated parameter settings instead of
// a single comma-separated list.
uriBuilder.appendQueryParameter("to", toList.get(i));
}
}
// Add the subject parameter.
if (subject != null) {
uriBuilder.appendQueryParameter("subject", subject);
}
// Add the subject parameter.
if (body != null) {
uriBuilder.appendQueryParameter("body", body);
}
// Add the cc parameters.
if (ccList != null && ccList.size() > 0) {
for (String email : ccList) {
uriBuilder.appendQueryParameter("cc", email);
}
}
// Insert the first email after 'mailto:' in the URI manually since Uri.Builder
// doesn't seem to have a way to do this.
String uri = uriBuilder.toString();
if (uri.startsWith("mailto:")) {
StringBuilder builder = new StringBuilder(uri);
builder.insert(7, Uri.encode(toList.get(0)));
uri = builder.toString();
}
// Start the email intent. Email from the account of the calendar owner in case there
// are multiple email accounts.
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse(uri));
emailIntent.putExtra("fromAccountString", ownerAccount);
// Workaround a Email bug that overwrites the body with this intent extra. If not
// set, it clears the body.
if (body != null) {
emailIntent.putExtra(Intent.EXTRA_TEXT, body);
}
return Intent.createChooser(emailIntent, resources.getString(R.string.email_picker_label));
}
/**
* Example fake email addresses used as attendee emails are resources like conference rooms,
* or another calendar, etc. These all end in "calendar.google.com".
*/
public static boolean isValidEmail(String email) {
return email != null && !email.endsWith(MACHINE_GENERATED_ADDRESS);
}
/**
* Returns true if:
* (1) the email is not a resource like a conference room or another calendar.
* Catch most of these by filtering out suffix calendar.google.com.
* (2) the email is not equal to the sync account to prevent mailing himself.
*/
public static boolean isEmailableFrom(String email, String syncAccountName) {
return Utils.isValidEmail(email) && !email.equals(syncAccountName);
}
private static class CalendarBroadcastReceiver extends BroadcastReceiver {
Runnable mCallBack;
public CalendarBroadcastReceiver(Runnable callback) {
super();
mCallBack = callback;
}
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_DATE_CHANGED) ||
intent.getAction().equals(Intent.ACTION_TIME_CHANGED) ||
intent.getAction().equals(Intent.ACTION_LOCALE_CHANGED) ||
intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
if (mCallBack != null) {
mCallBack.run();
}
}
}
}
public static BroadcastReceiver setTimeChangesReceiver(Context c, Runnable callback) {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_DATE_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(Intent.ACTION_LOCALE_CHANGED);
CalendarBroadcastReceiver r = new CalendarBroadcastReceiver(callback);
c.registerReceiver(r, filter);
return r;
}
public static void clearTimeChangesReceiver(Context c, BroadcastReceiver r) {
c.unregisterReceiver(r);
}
/**
* Return the app version code.
*/
public static String getVersionCode(Context context) {
if (sVersion == null) {
try {
sVersion = context.getPackageManager().getPackageInfo(
context.getPackageName(), 0).versionName;
} catch (PackageManager.NameNotFoundException e) {
// Can't find version; just leave it blank.
Log.e(TAG, "Error finding package " + context.getApplicationInfo().packageName);
}
}
return sVersion;
}
/**
* Checks the server for an updated list of Calendars (in the background).
*
* If a Calendar is added on the web (and it is selected and not
* hidden) then it will be added to the list of calendars on the phone
* (when this finishes). When a new calendar from the
* web is added to the phone, then the events for that calendar are also
* downloaded from the web.
*
* This sync is done automatically in the background when the
* SelectCalendars activity and fragment are started.
*
* @param account - The account to sync. May be null to sync all accounts.
*/
public static void startCalendarMetafeedSync(Account account) {
Bundle extras = new Bundle();
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
extras.putBoolean("metafeedonly", true);
ContentResolver.requestSync(account, Calendars.CONTENT_URI.getAuthority(), extras);
}
/**
* Replaces stretches of text that look like addresses and phone numbers with clickable
* links. If lastDitchGeo is true, then if no links are found in the textview, the entire
* string will be converted to a single geo link. Any spans that may have previously been
* in the text will be cleared out.
*
* This is really just an enhanced version of Linkify.addLinks().
*
* @param text - The string to search for links.
* @param lastDitchGeo - If no links are found, turn the entire string into one geo link.
* @return Spannable object containing the list of URL spans found.
*/
public static Spannable extendedLinkify(String text, boolean lastDitchGeo) {
// We use a copy of the string argument so it's available for later if necessary.
Spannable spanText = SpannableString.valueOf(text);
/*
* If the text includes a street address like "1600 Amphitheater Parkway, 94043",
* the current Linkify code will identify "94043" as a phone number and invite
* you to dial it (and not provide a map link for the address). For outside US,
* use Linkify result iff it spans the entire text. Otherwise send the user to maps.
*/
String defaultPhoneRegion = System.getProperty("user.region", "US");
if (!defaultPhoneRegion.equals("US")) {
Linkify.addLinks(spanText, Linkify.ALL);
// If Linkify links the entire text, use that result.
URLSpan[] spans = spanText.getSpans(0, spanText.length(), URLSpan.class);
if (spans.length == 1) {
int linkStart = spanText.getSpanStart(spans[0]);
int linkEnd = spanText.getSpanEnd(spans[0]);
if (linkStart <= indexFirstNonWhitespaceChar(spanText) &&
linkEnd >= indexLastNonWhitespaceChar(spanText) + 1) {
return spanText;
}
}
// Otherwise, to be cautious and to try to prevent false positives, reset the spannable.
spanText = SpannableString.valueOf(text);
// If lastDitchGeo is true, default the entire string to geo.
if (lastDitchGeo && !text.isEmpty()) {
Linkify.addLinks(spanText, mWildcardPattern, "geo:0,0?q=");
}
return spanText;
}
/*
* For within US, we want to have better recognition of phone numbers without losing
* any of the existing annotations. Ideally this would be addressed by improving Linkify.
* For now we manage it as a second pass over the text.
*
* URIs and e-mail addresses are pretty easy to pick out of text. Phone numbers
* are a bit tricky because they have radically different formats in different
* countries, in terms of both the digits and the way in which they are commonly
* written or presented (e.g. the punctuation and spaces in "(650) 555-1212").
* The expected format of a street address is defined in WebView.findAddress(). It's
* pretty narrowly defined, so it won't often match.
*
* The RFC 3966 specification defines the format of a "tel:" URI.
*
* Start by letting Linkify find anything that isn't a phone number. We have to let it
* run first because every invocation removes all previous URLSpan annotations.
*
* Ideally we'd use the external/libphonenumber routines, but those aren't available
* to unbundled applications.
*/
boolean linkifyFoundLinks = Linkify.addLinks(spanText,
Linkify.ALL & ~(Linkify.PHONE_NUMBERS));
/*
* Get a list of any spans created by Linkify, for the coordinate overlapping span check.
*/
URLSpan[] existingSpans = spanText.getSpans(0, spanText.length(), URLSpan.class);
/*
* Check for coordinates.
* This must be done before phone numbers because longitude may look like a phone number.
*/
Matcher coordMatcher = COORD_PATTERN.matcher(spanText);
int coordCount = 0;
while (coordMatcher.find()) {
int start = coordMatcher.start();
int end = coordMatcher.end();
if (spanWillOverlap(spanText, existingSpans, start, end)) {
continue;
}
URLSpan span = new URLSpan("geo:0,0?q=" + coordMatcher.group());
spanText.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
coordCount++;
}
/*
* Update the list of existing spans, for the phone number overlapping span check.
*/
existingSpans = spanText.getSpans(0, spanText.length(), URLSpan.class);
/*
* Search for phone numbers.
*
* Some URIs contain strings of digits that look like phone numbers. If both the URI
* scanner and the phone number scanner find them, we want the URI link to win. Since
* the URI scanner runs first, we just need to avoid creating overlapping spans.
*/
int[] phoneSequences = findNanpPhoneNumbers(text);
/*
* Insert spans for the numbers we found. We generate "tel:" URIs.
*/
int phoneCount = 0;
for (int match = 0; match < phoneSequences.length / 2; match++) {
int start = phoneSequences[match * 2];
int end = phoneSequences[match * 2 + 1];
if (spanWillOverlap(spanText, existingSpans, start, end)) {
continue;
}
/*
* The Linkify code takes the matching span and strips out everything that isn't a
* digit or '+' sign. We do the same here. Extension numbers will get appended
* without a separator, but the dialer wasn't doing anything useful with ";ext="
* anyway.
*/
//String dialStr = phoneUtil.format(match.number(),
// PhoneNumberUtil.PhoneNumberFormat.RFC3966);
StringBuilder dialBuilder = new StringBuilder();
for (int i = start; i < end; i++) {
char ch = spanText.charAt(i);
if (ch == '+' || Character.isDigit(ch)) {
dialBuilder.append(ch);
}
}
URLSpan span = new URLSpan("tel:" + dialBuilder.toString());
spanText.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
phoneCount++;
}
/*
* If lastDitchGeo, and no other links have been found, set the entire string as a geo link.
*/
if (lastDitchGeo && !text.isEmpty() &&
!linkifyFoundLinks && phoneCount == 0 && coordCount == 0) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "No linkification matches, using geo default");
}
Linkify.addLinks(spanText, mWildcardPattern, "geo:0,0?q=");
}
return spanText;
}
private static int indexFirstNonWhitespaceChar(CharSequence str) {
for (int i = 0; i < str.length(); i++) {
if (!Character.isWhitespace(str.charAt(i))) {
return i;
}
}
return -1;
}
private static int indexLastNonWhitespaceChar(CharSequence str) {
for (int i = str.length() - 1; i >= 0; i--) {
if (!Character.isWhitespace(str.charAt(i))) {
return i;
}
}
return -1;
}
/**
* Finds North American Numbering Plan (NANP) phone numbers in the input text.
*
* @param text The text to scan.
* @return A list of [start, end) pairs indicating the positions of phone numbers in the input.
*/
// @VisibleForTesting
static int[] findNanpPhoneNumbers(CharSequence text) {
ArrayList list = new ArrayList();
int startPos = 0;
int endPos = text.length() - NANP_MIN_DIGITS + 1;
if (endPos < 0) {
return new int[]{};
}
/*
* We can't just strip the whitespace out and crunch it down, because the whitespace
* is significant. March through, trying to figure out where numbers start and end.
*/
while (startPos < endPos) {
// skip whitespace
while (Character.isWhitespace(text.charAt(startPos)) && startPos < endPos) {
startPos++;
}
if (startPos == endPos) {
break;
}
// check for a match at this position
int matchEnd = findNanpMatchEnd(text, startPos);
if (matchEnd > startPos) {
list.add(startPos);
list.add(matchEnd);
startPos = matchEnd; // skip past match
} else {
// skip to next whitespace char
while (!Character.isWhitespace(text.charAt(startPos)) && startPos < endPos) {
startPos++;
}
}
}
int[] result = new int[list.size()];
for (int i = list.size() - 1; i >= 0; i--) {
result[i] = list.get(i);
}
return result;
}
/**
* Checks to see if there is a valid phone number in the input, starting at the specified
* offset. If so, the index of the last character + 1 is returned. The input is assumed
* to begin with a non-whitespace character.
*
* @return Exclusive end position, or -1 if not a match.
*/
private static int findNanpMatchEnd(CharSequence text, int startPos) {
/*
* A few interesting cases:
* 94043 # too short, ignore
* 123456789012 # too long, ignore
* +1 (650) 555-1212 # 11 digits, spaces
* (650) 555 5555 # Second space, only when first is present.
* (650) 555-1212, (650) 555-1213 # two numbers, return first
* 1-650-555-1212 # 11 digits with leading '1'
* *#650.555.1212#*! # 10 digits, include #*, ignore trailing '!'
* 555.1212 # 7 digits
*
* For the most part we want to break on whitespace, but it's common to leave a space
* between the initial '1' and/or after the area code.
*/
// Check for "tel:" URI prefix.
if (text.length() > startPos + 4
&& text.subSequence(startPos, startPos + 4).toString().equalsIgnoreCase("tel:")) {
startPos += 4;
}
int endPos = text.length();
int curPos = startPos;
int foundDigits = 0;
char firstDigit = 'x';
boolean foundWhiteSpaceAfterAreaCode = false;
while (curPos <= endPos) {
char ch;
if (curPos < endPos) {
ch = text.charAt(curPos);
} else {
ch = 27; // fake invalid symbol at end to trigger loop break
}
if (Character.isDigit(ch)) {
if (foundDigits == 0) {
firstDigit = ch;
}
foundDigits++;
if (foundDigits > NANP_MAX_DIGITS) {
// too many digits, stop early
return -1;
}
} else if (Character.isWhitespace(ch)) {
if ((firstDigit == '1' && foundDigits == 4) ||
(foundDigits == 3)) {
foundWhiteSpaceAfterAreaCode = true;
} else if (firstDigit == '1' && foundDigits == 1) {
} else if (foundWhiteSpaceAfterAreaCode
&& ((firstDigit == '1' && (foundDigits == 7)) || (foundDigits == 6))) {
} else {
break;
}
} else if (NANP_ALLOWED_SYMBOLS.indexOf(ch) == -1) {
break;
}
// else it's an allowed symbol
curPos++;
}
if ((firstDigit != '1' && (foundDigits == 7 || foundDigits == 10)) ||
(firstDigit == '1' && foundDigits == 11)) {
// match
return curPos;
}
return -1;
}
/**
* Determines whether a new span at [start,end) will overlap with any existing span.
*/
private static boolean spanWillOverlap(Spannable spanText, URLSpan[] spanList, int start,
int end) {
if (start == end) {
// empty span, ignore
return false;
}
for (URLSpan span : spanList) {
int existingStart = spanText.getSpanStart(span);
int existingEnd = spanText.getSpanEnd(span);
if ((start >= existingStart && start < existingEnd) ||
end > existingStart && end <= existingEnd) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
CharSequence seq = spanText.subSequence(start, end);
Log.v(TAG, "Not linkifying " + seq + " as phone number due to overlap");
}
return true;
}
}
return false;
}
}
================================================
FILE: library/src/main/java/be/billington/calendar/recurrencepicker/WeekButton.java
================================================
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package be.billington.calendar.recurrencepicker;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
public class WeekButton extends android.widget.ToggleButton {
private static int mWidth;
public WeekButton(Context context) {
super(context);
}
public WeekButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public WeekButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public static void setSuggestedWidth(int w) {
mWidth = w;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int h = getMeasuredHeight();
int w = getMeasuredWidth();
if (h > 0 && w > 0) {
if (w < h) {
if (View.MeasureSpec.getMode(getMeasuredHeightAndState()) != MeasureSpec.EXACTLY) {
h = w;
}
} else if (h < w) {
if (View.MeasureSpec.getMode(getMeasuredWidthAndState()) != MeasureSpec.EXACTLY) {
w = h;
}
}
}
setMeasuredDimension(w, h);
}
}
================================================
FILE: library/src/main/res/color/done_text_color.xml
================================================
================================================
FILE: library/src/main/res/color/recurrence_bubble_text_color.xml
================================================
================================================
FILE: library/src/main/res/color/recurrence_spinner_text_color.xml
================================================
================================================
FILE: library/src/main/res/drawable/recurrence_bubble_fill.xml
================================================
================================================
FILE: library/src/main/res/drawable/switch_thumb.xml
================================================
================================================
FILE: library/src/main/res/layout/recurrencepicker.xml
================================================
================================================
FILE: library/src/main/res/layout/recurrencepicker_end_text.xml
================================================
================================================
FILE: library/src/main/res/layout/recurrencepicker_freq_item.xml
================================================
================================================
FILE: library/src/main/res/values/arrays.xml
================================================
NotificationEmailSMSAlarm12340 minutes1 minute5 minutes10 minutes15 minutes20 minutes25 minutes30 minutes45 minutes1 hour2 hours3 hours12 hours24 hours2 days1 week015101520253045601201807201440288010080BusyAvailableTentative012DefaultPrivatePublicfirstsecondthirdfourthlastNo responseYesMaybeNoOnly this eventThis and future eventsAll events012This & future eventsAll eventsOnly this eventAll events in the seriesDayWeekMonthAgendaOnly if declinedIf declined or not respondeddeclinednot_respondedREPEAT DAILYREPEAT WEEKLYREPEAT MONTHLYREPEAT YEARLYon every first Sundayon every second Sundayon every third Sundayon every fourth Sundayon every last Sundayon every first Mondayon every second Mondayon every third Mondayon every fourth Mondayon every last Mondayon every first Tuesdayon every second Tuesdayon every third Tuesdayon every fourth Tuesdayon every last Tuesdayon every first Wednesdayon every second Wednesdayon every third Wednesdayon every fourth Wednesdayon every last Wednesdayon every first Thursdayon every second Thursdayon every third Thursdayon every fourth Thursdayon every last Thursdayon every first Fridayon every second Fridayon every third Fridayon every fourth Fridayon every last Fridayon every first Saturdayon every second Saturdayon every third Saturdayon every fourth Saturdayon every last Saturday
================================================
FILE: library/src/main/res/values/colors.xml
================================================
#330066ff@android:color/holo_blue_light#ffcccccc#ff333333#0033b5e5#fafafa#ffc3d9ff#ffffffff#ffFFFFFF#777777#80000000#80333333#80333333#ffffffff#ff666666#ff999999#ffEEEEEE#FFEEEEEE#ff666666#e633b5e5#FFCCCCCC#FFCCCCCC#ff707070#FFFFFFFF#FF000000#FF333333#FF000000#FF999999#FF999999#FF999999#FF333333#FF333333#FF666666#FF666666#4C999999#80333333#80333333#ffCCCCCC#ff939497#FFEEEEEE#FFDDDDDD#FFFFFFFF#FFE5E5E5#FF333333#ff6bd697#FFDDDDDD#ff000000#ff808080#ff323232#ff808080#00000000#66333333#FF333333#FFFFFFFF#FFDDDDDD#FF333333#FFEEEEEE#FF666666#FF666666#66666666#FF666666#FF888888#FFBBBBBB@android:color/holo_blue_dark#FFFFFFFF#FFFFFFFF#8033B5E5#FF33B5E5#FFDDDDDD#FFFFFFFF#B3FFFFFF#FFFFFFFF#FF666666#FF666666#FF666666#FF999999#FFDDDDDD#FF000000#FF888888#FFDDDDDD#4D000000#FFFFFFFF#FF999999#8F999999#6633b5e5#ffEEEEEE@android:color/white#ffEEEEEE#66333333#ff333333#ffffffff#ffffffff#ffffffff#ffffffff#ffffffff#fff2f2f2#ff737373
================================================
FILE: library/src/main/res/values/dimens.xml
================================================
340dp300dp
================================================
FILE: library/src/main/res/values/strings.xml
================================================
Email guestsEmail organizerEmail withRe:\u0020Done"Snooze all""Dismiss all""Snooze"One-time event; until %s; for one time; for %d timesDailyEvery %d days"Every weekday (Mon\u2013Fri)"Weekly on %2$sEvery %1$d weeks on %2$sMonthlyYearly"Monthly (on day %s)""Yearly (on %s)"RepeatNever repeatsEvery %d dayEvery %d daysEvery %d weekEvery %d weeksEvery %d monthEvery %d monthsEvery %d yearEvery %d yearson the same day each monthForeverUntil a dateUntil %sFor a number of eventsFor %d eventFor %d eventschange end date
================================================
FILE: library/src/main/res/values/styles.xml
================================================
================================================
FILE: library/src/main/res/values-af/arrays.xml
================================================
"Kennisgewing""E-pos""SMS""Alarm""0 minute""1 minuut""5 minute""10 minute""15 minute""20 minute""25 minute""30 minute""45 minute""1 uur""2 uur""3 uur""12 uur""24 uur""2 dae""1 week""Geen""0 minute""1 minuut""5 minute""10 minute""15 minute""20 minute""25 minute""30 minute""45 minute""1 uur""2 uur""3 uur""12 uur""24 uur""2 dae""1 week""Locale-verstek""Saterdag""Sondag""Maandag""Besig""Beskikbaar""Voorlopig""Verstek""Privaat""Publiek""eerste""sekonde""derde""vierde""laaste""Geen reaksie nie""Ja""Miskien""Nee""Slegs hierdie gebeurtenis""Hierdie en toekomstige gebeure""Alle gebeurtenisse""Hierdie en toekomstige gebeurtenisse""Alle gebeurtenisse""Slegs hierdie gebeurtenis""Alle gebeurtenisse in die reeks""Dag""Week""Maand""Agenda""Net as afgewys""As afgewys of nie gereageer nie""HERHAAL DAAGLIKS""HERHAAL WEEKLIKS""HERHAAL MAANDELIKS""HERHAAL JAARLIKS""op elke eerste Sondag""op elke tweede Sondag""op elke derde Sondag""op elke vierde Sondag""op elke laaste Sondag""op elke eerste Maandag""op elke tweede Maandag""op elke derde Maandag""op elke vierde Maandag""op elke laaste Maandag""op elke eerste Dinsdag""op elke tweede Dinsdag""op elke derde Dinsdag""op elke vierde Dinsdag""op elke laaste Dinsdag""op elke eerste Woensdag""op elke tweede Woensdag""op elke derde Woensdag""op elke vierde Woensdag""op elke laaste Woensdag""op elke eerste Donderdag""op elke tweede Donderdag""op elke derde Donderdag""op elke vierde Donderdag""op elke laaste Donderdag""op elke eerste Vrydag""op elke tweede Vrydag""op elke derde Vrydag""op elke vierde Vrydag""op elke laaste Vrydag""op elke eerste Saterdag""op elke tweede Saterdag""op elke derde Saterdag""op elke vierde Saterdag""op elke laaste Saterdag"
================================================
FILE: library/src/main/res/values-af/strings.xml
================================================
"E-pos met""Klaar""Herhaal""Herhaal nooit nie""Elke %d dag""Elke %d dae""Elke %d week""Elke %d weke""Elke %d maand""Elke %d maande""Elke %d jaar""Elke %d jaar""op dieselfde dag elke maand""Vir altyd""Tot \'n datum""Tot %s""Vir \'n aantal geleenthede""Vir %d geleentheid""Vir %d geleenthede""verander einddatum"
================================================
FILE: library/src/main/res/values-am/arrays.xml
================================================
"ማሳወቂያ""ኢሜይል""አጭር የፅሁፍ መልዕክት""ማንቂያ ደውል""0 ደቂቃዎች""1 ደቂቃ""5 ደቂቃዎች""10 ደቂቃዎች""15 ደቂቃዎች""20 ደቂቃዎች""25 ደቂቃዎች""30 ደቂቃዎች""45 ደቂቃዎች""1 ሰዓት""2 ሰዓቶች""3 ሰዓቶች""12 ሰዓቶች""24 ሰዓቶች""2 ቀኖች""1 ሳምንት""የለም""0 ደቂቃዎች""1 ደቂቃ""5 ደቂቃዎች""10 ደቂቃዎች""15 ደቂቃዎች""20 ደቂቃዎች""25 ደቂቃዎች""30 ደቂቃዎች""45 ደቂቃዎች""1 ሰዓት""2 ሰዓቶች""3 ሰዓቶች""12 ሰዓቶች""24 ሰዓቶች""2 ቀኖች""1 ሳምንት""የአካባቢ ነባሪ""ቅዳሜ""እሁድ""ሰኞ""ተይዟ ል""የሚገኝ""ጊዜያዊ""ነባሪ""የግል""ሕዝብ""አንደኛ""ሁለተኛ""ሦስተኛ""አራተኛ""መጨረሻ""ምንም ምላሽ የለም""አዎ""ምናልባት""አይ""ይህ ክስተት ብቻ""ይሄ እና የወደፊት ክስተቶች""ሁሉም ክስተቶች""ይህ& የወደፊት ዝግጅቶች""ሁሉም ክስተቶች""ይህ ክስተት ብቻ""ሁሉም ዝግጅቶች በተከታታይ""ቀን""ሳምንት""ወር""አጀንዳ""ተቀባይነት ካላገኘ ብቻ""ተቀባይነት ካላገኘ ወይም ምላሽ ካልተሰጠበት""በየቀኑ ድገም""በየሳምንቱ ድገም""በየወሩ ድገም""በየዓመቱ ድገም""በሁሉም የመጀመሪያ እሁድ""በሁሉም ሁለተኛ እሁድ""በሁሉም ሶስተኛ እሁድ""በሁሉም አራተኛ እሁድ""በሁሉም የመጨረሻ እሁድ""በሁሉም የመጀመሪያ ሰኞ""በሁሉም ሁለተኛ ሰኞ""በሁሉም ሶስተኛ ሰኞ""በሁሉም አራተኛ ሰኞ""በሁሉም የመጨረሻ ሰኞ""በሁሉም የመጀመሪያ ማክሰኞ""በሁሉም ሁለተኛ ማክሰኞ""በሁሉም ሶስተኛ ማክሰኞ""በሁሉም አራተኛ ማክሰኞ""በሁሉም የመጨረሻ ማክሰኞ""በሁሉም የመጀመሪያ ረቡዕ""በሁሉም ሁለተኛ ረቡዕ""በሁሉም ሶስተኛ ረቡዕ""በሁሉም አራተኛ ረቡዕ""በሁሉም የመጨረሻ ረቡዕ""በሁሉም የመጀመሪያ ሃሙስ""በሁሉም ሁለተኛ ሃሙስ""በሁሉም ሶስተኛ ሃሙስ""በሁሉም አራተኛ ሃሙስ""በሁሉም የመጨረሻ ሃሙስ""በሁሉም የመጀመሪያ አርብ""በሁሉም ሁለተኛ አርብ""በሁሉም ሶስተኛ አርብ""በሁሉም አራተኛ አርብ""በሁሉም የመጨረሻ አርብ""በሁሉም የመጀመሪያ ቅዳሜ""በሁሉም ሁለተኛ ቅዳሜ""በሁሉም ሶስተኛ ቅዳሜ""በሁሉም አራተኛ ቅዳሜ""በሁሉም የመጨረሻ ቅዳሜ"
================================================
FILE: library/src/main/res/values-am/strings.xml
================================================
"በነዚህ ኢሜይል ላክ""ተከናውኗል""ድገም""በጭራሽ አይደገምም""በየ%d ቀን""በየ%d ቀን""በየ%d ሳምንት""በየ%d ሳምንት""በየ%d ወር""በየ%d ወር""በየ%d ዓመት""በየ%d ዓመት""በየወሩ በተመሳሳዩ ቀን ላይ""ለዘለዓለም""እስከ አንድ ቀን ድረስ""እስከ %s ድረስ""ለተወሰነ የክስተቶች ብዛት""ለ%d ክስተት""ለ%d ክስተቶች""የመጨረሻውን ቀን ቀይር"
================================================
FILE: library/src/main/res/values-ar/arrays.xml
================================================
"إشعار""بريد إلكتروني""رسائل SMS""المنبه""0 دقائق""دقيقة واحدة""5 دقائق""10 دقائق""15 دقيقة""20 دقيقة""25 دقيقة""30 دقيقة""45 دقيقة""ساعة واحدة""ساعتان""3 ساعات""12 ساعة""24 ساعة""يومان""أسبوع واحد""لا شيء""0 دقائق""دقيقة واحدة""5 دقائق""10 دقائق""15 دقيقة""20 دقيقة""25 دقيقة""30 دقيقة""45 دقيقة""ساعة واحدة""ساعتان""3 ساعات""12 ساعة""24 ساعة""يومان""أسبوع واحد""اللغة الافتراضية""السبت""الأحد""الاثنين""مشغول""متواجد""مبدئي""افتراضي""خاص""عام""أول""ثانية""الثالث""الرابع""الأخير""لا استجابة""نعم""ربما""لا""هذا الحدث فقط""هذا الحدث والأحداث المستقبلية""جميع الأحداث""هذا الحدث والأحداث المستقبلية""جميع الأحداث""هذا الحدث فقط""جميع الأحداث في سلسلة الأحداث""يوم""أسبوع""شهر""أجندة""في حالة الرفض فقط""في حالة الرفض أو عدم الرد""التكرار يوميًا""التكرار أسبوعيًا""التكرار شهريًا""التكرار سنويًا""يوم الأحد الأول من كل شهر""يوم الأحد الثاني من كل شهر""يوم الأحد الثالث من كل شهر""يوم الأحد الرابع من كل شهر""يوم الأحد الأخير من كل شهر""يوم الاثنين الأول من كل شهر""يوم الاثنين الثاني من كل شهر""يوم الاثنين الثالث من كل شهر""يوم الاثنين الرابع من كل شهر""يوم الاثنين الأخير من كل شهر""يوم الثلاثاء الأول من كل شهر""يوم الثلاثاء الثاني من كل شهر""يوم الثلاثاء الثالث من كل شهر""يوم الثلاثاء الرابع من كل شهر""يوم الثلاثاء الأخير من كل شهر""يوم الأربعاء الأول من كل شهر""يوم الأربعاء الثاني من كل شهر""يوم الأربعاء الثالث من كل شهر""يوم الأربعاء الرابع من كل شهر""يوم الأربعاء الأخير من كل شهر""يوم الخميس الأول من كل شهر""يوم الخميس الثاني من كل شهر""يوم الخميس الثالث من كل شهر""يوم الخميس الرابع من كل شهر""يوم الخميس الأخير من كل شهر""يوم الجمعة الأول من كل شهر""يوم الجمعة الثاني من كل شهر""يوم الجمعة الثالث من كل شهر""يوم الجمعة الرابع من كل شهر""يوم الجمعة الأخير من كل شهر""يوم السبت الأول من كل شهر""يوم السبت الثاني من كل شهر""يوم السبت الثالث من كل شهر""يوم السبت الرابع من كل شهر""يوم السبت الأخير من كل شهر"
================================================
FILE: library/src/main/res/values-ar/strings.xml
================================================
"إرسال رسالة إلكترونية إلى""تم""التكرار""لا يتكرر""كل %d يوم""كل %d يوم""كل %d أسبوع""كل %d أسبوع""كل %d شهر""كل %d شهر""كل %d عام""كل %d عام""في اليوم نفسه من كل شهر""للأبد""حتى تاريخ ما""حتى %s""لعدد من الأحداث""لـ %d حدث""لـ %d من الأحداث""تغيير تاريخ الانتهاء"
================================================
FILE: library/src/main/res/values-be/arrays.xml
================================================
"Апавяшч-е""Электр. пошта""SMS""Будзільнік""0 хвілін""1 хвіліна""5 хвілін""10 хвілін""15 хвілін""20 хвілін""25 хвілін""30 хвілін""45 хвілін""1 гадзіна""2 гадзіны""3 гадзіны""12 гадзін""24 гадзіны""2 дні""1 тыдзень""Няма""0 хвілін""1 хвіліна""5 хвілін""10 хвілін""15 хвілін""20 хвілін""25 хвілін""30 хвілін""45 хвілін""1 гадзіна""2 гадзіны""3 гадзіны""12 гадзін""24 гадзіны""2 дні""1 тыдзень""Рэгiянальная налада па змаўчанні""Субота""Нядзеля""Панядзелак""Заняты""Даступны""Часова""Па змаўчанні""Прыватны""Агульнадаступнае""першы""другі""трэці""чацвёрты""апошні""Няма адказу""Так""Магчыма""Не""Толькі гэта падзея""Гэта і будучыя мерапрыемствы""Усе падзеі""Гэтыя i будучыя падзеі""Усе падзеі""Толькі гэта мерапрыемства""Усе падзеі ў серыі""Дзень""Тыдзень""Месяц""Парадак дня""Толькі калі адмоўлена""Калі адмоўлена або адказу няма""ШТОДЗЁННЫ ПАЎТОР""ШТОТЫДНЁВЫ ПАЎТОР""ШТОМЕСЯЧНЫ ПАЎТОР""ШТОГАДОВЫ ПАЎТОР""кожную першую нядзелю""кожную другую нядзелю""кожную трэцюю нядзелю""кожную чацвёртую нядзелю""кожную апошнюю нядзелю""кожны першы панядзелак""кожны другі панядзелак""кожны трэці панядзелак""кожны чацвёрты панядзелак""кожны апошні панядзелак""кожны першы аўторак""кожны другі аўторак""кожны трэці аўторак""кожны чацвёрты аўторак""кожны апошні аўторак""кожную першую сераду""кожную другую сераду""кожную трэцюю сераду""кожную чацвёртую сераду""кожную апошнюю сераду""кожны першы чацвер""кожны другі чацвер""кожны трэці чацвер""кожны чацвёрты чацвер""кожны апошні чацвер""кожную першую пятніцу""кожную другую пятніцу""кожную трэцюю пятніцу""кожную чацвёртую пятніцу""кожную апошнюю пятніцу""кожную першую суботу""кожную другую суботу""кожную трэцюю суботу""кожную чацвёртую суботу""кожную апошнюю суботу"
================================================
FILE: library/src/main/res/values-be/strings.xml
================================================
"Электронная пошта з""Адкласці ўсе""Адмяніць усё""Адкласці""Аднаразовая падзея""; да %s""; на адзін раз""; для %d р.""Штодзённа""Кожн. %d д.""Кожны будны дзень (Пн–Пт)""Кожны тыдзень па %2$s""Кожныя %1$d тыд. па %2$s""Штомесяц""Штогод""Штомесяц (у дзень %s)""Штогод (па %s)""Гатова""Паўтарыць""Ніколі не паўтараецца""Кожны %d дзень""Кожны %d дзень""Кожны %d тыдз.""Кожныя %d тыдняў""Кожны %d месяц""Кожныя %d мес.""Кожны %d год""Кожныя %d гадоў""у той жа дзень кожнага месяца""Назаўсёды""Да даты""да %s""Для некалькiх мерапрыемстваў""Для мерапрыемства %d""Для мерапрыемства %d""змяніць дату заканчэння"
================================================
FILE: library/src/main/res/values-bg/arrays.xml
================================================
"Известие""Имейл""SMS""Будилник""0 минути""1 минута""5 минути""10 минути""15 минути""20 минути""25 минути""30 минути""45 минути""1 час""2 часа""3 часа""12 часа""24 часа""2 дни""1 седмица""Няма""0 минути""1 минута""5 минути""10 минути""15 минути""20 минути""25 минути""30 минути""45 минути""1 час""2 часа""3 часа""12 часа""24 часа""2 дни""1 седмица""Стандартно за локала""събота""неделя""понеделник""Зает/а""На разположение""Колебливо""Стандартно""Частно""Обществено""първо""второ""трето""четвърто""посл.""Няма отговор""Да""Може би""Не""Само това събитие""Това и бъдещи събития""Всички събития""Това и бъдещи събития""Всички събития""Само това събитие""Всички събития в поредицата""Ден""Седмица""Месец""График""Само при отхвърляне""При отхвърляне или липса на отговор""ПОВТАРЯНЕ ДНЕВНО""ПОВТАРЯНЕ СЕДМИЧНО""ПОВТАРЯНЕ МЕСЕЧНО""ПОВТАРЯНЕ ГОДИШНО""всяка първа неделя""всяка втора неделя""всяка трета неделя""всяка четвърта неделя""всяка последна неделя""всеки първи понеделник""всеки втори понеделник""всеки трети понеделник""всеки четвърти понеделник""всеки последен понеделник""всеки първи вторник""всеки втори вторник""всеки трети вторник""всеки четвърти вторник""всеки последен вторник""всяка първа сряда""всяка втора сряда""всяка трета сряда""всяка четвърта сряда""всяка последна сряда""всеки първи четвъртък""всеки втори четвъртък""всеки трети четвъртък""всеки четвърти четвъртък""всеки последен четвъртък""всеки първи петък""всеки втори петък""всеки трети петък""всеки четвърти петък""всеки последен петък""всяка първа събота""всяка втора събота""всяка трета събота""всяка четвърта събота""всяка последна събота"
================================================
FILE: library/src/main/res/values-bg/strings.xml
================================================
"Изпращане на имейл посредством""Готово""Повтаряне""Без повтаряне""На %d ден""На %d дни""На %d седмица""На %d седмици""На %d месец""На %d месеца""На %d година""На %d години""на същия ден всеки месец""Винаги""До дадена дата""До %s""За даден брой събития""За %d събитие""За %d събития""промяна на крайната дата"
================================================
FILE: library/src/main/res/values-ca/arrays.xml
================================================
"Notificació""Correu electrònic""SMS""Alarma""0 minuts""1 minut""5 minuts""10 minuts""15 minuts""20 minuts""25 minuts""30 minuts""45 minuts""1 hora""2 hores""3 hores""12 hores""24 hores""2 dies""1 setmana""Cap""0 minuts""1 minut""5 minuts""10 minuts""15 minuts""20 minuts""25 minuts""30 minuts""45 minuts""1 hora""2 hores""3 hores""12 hores""24 hores""2 dies""1 setmana""Regió predeterminada""Dissabte""Diumenge""Dilluns""Ocupat""Disponible""Provisional""Predeterminada""Privat""Públic""primer""segon""tercer""quart""darrer""Cap resposta""Sí""Potser""No""Només aquest esdeveniment""Aquest esdeveniment i esdeveniments futurs""Tots els esdeveniments""Aquest i els esdeveniments futurs""Tots els esdeveniments""Només aquest esdeveniment""Tots els esdeveniments de la sèrie""Dia""Setmana""Mes""Agenda""Només si es rebutja""Si es rebutja o no es contesta""REPETEIX DIÀRIAMENT""REPETEIX SETMANALMENT""REPETEIX MENSUALMENT""REPETEIX ANUALMENT""primer diumenge de cada mes""segon diumenge de cada mes""tercer diumenge de cada mes""quart diumenge de cada mes""últim diumenge de cada mes""primer dilluns de cada mes""segon dilluns de cada mes""tercer dilluns de cada mes""quart dilluns de cada mes""últim dilluns de cada mes""primer dimarts de cada mes""segon dimarts de cada mes""tercer dimarts de cada mes""quart dimarts de cada mes""últim dimarts de cada mes""primer dimecres de cada mes""segon dimecres de cada mes""tercer dimecres de cada mes""quart dimecres de cada mes""últim dimecres de cada mes""primer dijous de cada mes""segon dijous de cada mes""tercer dijous de cada mes""quart dijous de cada mes""últim dijous de cada mes""primer divendres de cada mes""segon divendres de cada mes""tercer divendres de cada mes""quart divendres de cada mes""últim divendres de cada mes""primer dissabte de cada mes""segon dissabte de cada mes""tercer dissabte de cada mes""quart dissabte de cada mes""últim dissabte de cada mes"
================================================
FILE: library/src/main/res/values-ca/strings.xml
================================================
"Correu electrònic amb""Fet""Repeteix""No es repeteix mai""Cada %d dia""Cada %d dies""Cada %d setmana""Cada %d setmanes""Cada %d mes""Cada %d mesos""Cada %d any""Cada %d anys""el mateix dia de cada mes""Sempre""Fins a una data""Fins al dia %s""Per a alguns esdeveniments""Per a %d esdeveniment""Per a %d esdeveniments""canvia la data de finalització"
================================================
FILE: library/src/main/res/values-cs/arrays.xml
================================================
"Oznámení""E-mail""SMS""Budík""0 minut""1 minuta""5 minut""10 minut""15 minut""20 minut""25 minut""30 minut""45 minut""1 hodina""2 hodiny""3 hodiny""12 hodin""24 hodin""2 dny""1 týden""Žádné""0 minut""1 minuta""5 minut""10 minut""15 minut""20 minut""25 minut""30 minut""45 minut""1 hodina""2 hodiny""3 hodiny""12 hodin""24 hodin""2 dny""1 týden""Výchozí hodnota regionálního nastavení""Sobota""Neděle""Pondělí""Nemám čas""K dispozici""Možná""Výchozí nastavení""Soukromá""Veřejná""1.""2.""3.""4.""poslední""Žádná odpověď""Ano""Možná""Ne""Pouze tato událost""Tato a budoucí události""Všechny události""Tato a budoucí události""Všechny události""Pouze tato událost""Všechny instance události""Den""Týden""Měsíc""Agenda""Jen v případě odmítnutí""Při odmítnutí nebo bez odpovědi""OPAKOVAT DENNĚ""OPAKOVAT TÝDNĚ""OPAKOVAT MĚSÍČNĚ""OPAKOVAT ROČNĚ""každou první neděli""každou druhou neděli""každou třetí neděli""každou čtvrtou neděli""každou poslední neděli""každé první pondělí""každé druhé pondělí""každé třetí pondělí""každé čtvrté pondělí""každé poslední pondělí""každé první úterý""každé druhé úterý""každé třetí úterý""každé čtvrté úterý""každé poslední úterý""každou první středu""každou druhou středu""každou třetí středu""každou čtvrtou středu""každou poslední středu""každý první čtvrtek""každý druhý čtvrtek""každý třetí čtvrtek""každý čtvrtý čtvrtek""každý poslední čtvrtek""každý první pátek""každý druhý pátek""každý třetí pátek""každý čtvrtý pátek""každý poslední pátek""každou první sobotu""každou druhou sobotu""každou třetí sobotu""každou čtvrtou sobotu""každou poslední sobotu"
================================================
FILE: library/src/main/res/values-cs/strings.xml
================================================
"Psát si s uživateli""Hotovo""Opakování""Neopakuje se""Jednou za %d d.""Jednou za %d d.""Jednou za %d týd.""Jednou za %d týd.""Jednou za %d měs.""Jedno za %d měs.""Jednou za %d r.""Jednou za %d r.""měsíčně tentýž den""Navždy""Do určitého data""Do %s""Po určitý počet událostí""Pro %d událost""Pro následující počet událostí: %d""změnit datum ukončení"
================================================
FILE: library/src/main/res/values-da/arrays.xml
================================================
"Meddelelse""E-mail""Sms""Påmindelse""0 minutter""1 minut""5 minutter""10 minutter""15 minutter""20 minutter""25 minutter""30 minutter""45 minutter""1 time""2 timer""3 timer""12 timer""24 timer""2 dage""1 uge""Ingen""0 minutter""1 minut""5 minutter""10 minutter""15 minutter""20 minutter""25 minutter""30 minutter""45 minutter""1 time""2 timer""3 timer""12 timer""24 timer""2 dage""1 uge""Landestandard""lørdag""søndag""mandag""Optaget""Ledig""Foreløbig""Standard""Privat""Offentlig""først""anden""tredje""fjerde""sidst""Intet svar""Ja""Måske""Nej""Kun denne begivenhed""Denne og fremtidige begivenheder""Alle begivenheder""Denne og fremtidige begivenheder""Alle begivenheder""Kun denne begivenhed""Alle begivenheder i serien""Dag""Uge""Måned""Dagsorden""Kun hvis afvist""Hvis afvist eller der ikke reageres""GENTAG DAGLIGT""GENTAG UGENTLIGT""GENTAG MÅNEDLIGT""GENTAG ÅRLIGT""hver første søndag i måneden""hver anden søndag""hver tredje søndag""hver fjerde søndag""hver sidste søndag i måneden""hver første mandag i måneden""hver anden mandag""hver tredje mandag""hver fjerde mandag""hver sidste mandag i måneden""hver første tirsdag i måneden""hver anden tirsdag""hver tredje tirsdag""hver fjerde tirsdag""hver sidste tirsdag i måneden""hver første onsdag i måneden""hver anden onsdag""hver tredje onsdag""hver fjerde onsdag""hver sidste onsdag i måneden""hver første torsdag i måneden""hver anden torsdag""hver tredje torsdag""hver fjerde torsdag""hver sidste torsdag i måneden""hver første fredag i måneden""hver anden fredag""hver tredje fredag""hver fjerde fredag""hver sidste fredag i måneden""hver første lørdag i måneden""hver anden lørdag""hver tredje lørdag""hver fjerde lørdag""hver sidste lørdag i måneden"
================================================
FILE: library/src/main/res/values-da/strings.xml
================================================
"Send e-mail til""Gem""Gentag""Gentages aldrig""%d gang om dagen""Hver %d. dag""%d gang om ugen""Hver %d. uge""%d gang om måneden""Hver %d. måned""%d gang om året""Hvert %d. år""samme dag hver måned""For altid""Frem til en bestemt dato""Indtil %s""Et antal gange""For %d begivenhed""For %d begivenheder""skift slutdato"
================================================
FILE: library/src/main/res/values-de/arrays.xml
================================================
"Benachrichtigung""E-Mail""SMS""Wecker""0 Minuten""1 Minute""5 Minuten""10 Minuten""15 Minuten""20 Minuten""25 Minuten""30 Minuten""45 Minuten""1 Stunde""2 Stunden""3 Stunden""12 Stunden""24 Stunden""2 Tage""1 Woche""Keine""0 Minuten""1 Minute""5 Minuten""10 Minuten""15 Minuten""20 Minuten""25 Minuten""30 Minuten""45 Minuten""1 Stunde""2 Stunden""3 Stunden""12 Stunden""24 Stunden""2 Tage""1 Woche""Gebietsschema - Standard""Samstag""Sonntag""Montag""Beschäftigt""Verfügbar""Mit Vorbehalt""Standard""Privat""Öffentlich""1.""2.""3.""4.""letzten""Keine Antwort""Ja""Vielleicht""Nein""Nur dieser Termin""Dieser und zukünftige Termine""Alle Termine""Dieser und zukünftige Termine""Alle Termine""Nur diesen Termin""Alle Termine in der Reihe""Tag""Woche""Monat""Terminübersicht""Nur bei Ablehnung""Bei Ablehnung oder keine Antwort""Täglich""Jede Woche""Jeden Monat""Jedes Jahr""an jedem ersten Sonntag""an jedem zweiten Sonntag""an jedem dritten Sonntag""an jedem vierten Sonntag""an jedem letzten Sonntag""an jedem ersten Montag""an jedem zweiten Montag""an jedem dritten Montag""an jedem vierten Montag""an jedem letzten Montag""an jedem ersten Dienstag""an jedem zweiten Dienstag""an jedem dritten Dienstag""an jedem vierten Dienstag""an jedem letzten Dienstag""an jedem ersten Mittwoch""an jedem zweiten Mittwoch""an jedem dritten Mittwoch""an jedem vierten Mittwoch""an jedem letzten Mittwoch""an jedem ersten Donnerstag""an jedem zweiten Donnerstag""an jedem dritten Donnerstag""an jedem vierten Donnerstag""an jedem letzten Donnerstag""an jedem ersten Freitag""an jedem zweiten Freitag""an jedem dritten Freitag""an jedem vierten Freitag""an jedem letzten Freitag""an jedem ersten Samstag""an jedem zweiten Samstag""an jedem dritten Samstag""an jedem vierten Samstag""an jedem letzten Samstag"
================================================
FILE: library/src/main/res/values-de/strings.xml
================================================
"E-Mail über""Fertig""Wiederholen""Einmaliger Termin""Nach %d Tag""Alle %d Tage""Nach %d Woche""Alle %d Wochen""Nach %d Monat""Alle %d Monate""Nach %d Jahr""Alle %d Jahre""am gleichen Tag des Monats""Dauerhaft""Bis zu bestimmtem Datum""Bis %s""Mehrere Wiederholungen""%d-mal""%d-mal""Enddatum ändern"
================================================
FILE: library/src/main/res/values-el/arrays.xml
================================================
"Ειδοποίηση""Ηλ. ταχυδρομείο""SMS""Ξυπνητήρι""0 λεπτά""1 λεπτό""5 λεπτά""10 λεπτά""15 λεπτά""20 λεπτά""25 λεπτά""30 λεπτά""45 λεπτά""1 ώρα""2 ώρες""3 ώρες""12 ώρες""24 ώρες""2 ημέρες""1 εβδομάδα""Κανένα""0 λεπτά""1 λεπτό""5 λεπτά""10 λεπτά""15 λεπτά""20 λεπτά""25 λεπτά""30 λεπτά""45 λεπτά""1 ώρα""2 ώρες""3 ώρες""12 ώρες""24 ώρες""2 ημέρες""1 εβδομάδα""Προεπιλογή τοπικών ρυθμίσεων""Σάββατο""Κυριακή""Δευτέρα""Απασχολημένος/η""Διαθέσιμος/η""Αβέβαιη παρουσία""Προεπιλογή""Ιδιωτικό""Δημόσιο""πρώτο""δεύτερο""τρίτο""τέταρτο""τελευταία""Καμία απάντηση""Ναι""Ίσως""Όχι""Μόνο αυτό το συμβάν""Αυτό και τα μελλοντικά συμβάντα""Όλα τα συμβάντα""Αυτά & τα μελλοντικά συμβάντα""Όλα τα συμβάντα""Μόνο αυτό το συμβάν""Όλα τα συμβάντα στη σειρά""Ημέρα""Εβδομάδα""Μήνας""Ατζέντα""Μόνο μετά από απόρριψη""Μετά από απόρριψη ή μη απόκριση""ΕΠΑΝΑΛΗΨΗ ΚΑΘΗΜΕΡΙΝΑ""ΕΠΑΝΑΛΗΨΗ ΕΒΔΟΜΑΔ.""ΕΠΑΝΑΛΗΨΗ ΜΗΝΙΑΙΑ""ΕΠΑΝΑΛΗΨΗ ΕΤΗΣΙΩΣ""κάθε πρώτη Κυριακή""κάθε δεύτερη Κυριακή""κάθε τρίτη Κυριακή""κάθε τέταρτη Κυριακή""κάθε προηγούμενη Κυριακή""κάθε πρώτη Δευτέρα""κάθε δεύτερη Δευτέρα""κάθε τρίτη Δευτέρα""κάθε τέταρτη Δευτέρα""κάθε προηγούμενη Δευτέρα""κάθε πρώτη Τρίτη""κάθε δεύτερη Τρίτη""κάθε τρίτη Τρίτη""κάθε τέταρτη Τρίτη""κάθε προηγούμενη Τρίτη""κάθε πρώτη Τετάρτη""κάθε δεύτερη Τετάρτη""κάθε τρίτη Τετάρτη""κάθε τέταρτη Τετάρτη""κάθε προηγούμενη Τετάρτη""κάθε πρώτη Πέμπτη""κάθε δεύτερη Πέμπτη""κάθε τρίτη Πέμπτη""κάθε τέταρτη Πέμπτη""κάθε προηγούμενη Πέμπτη""κάθε πρώτη Παρασκευή""κάθε δεύτερη Παρασκευή""κάθε τρίτη Παρασκευή""κάθε τέταρτη Παρασκευή""κάθε προηγούμενη Παρασκευή""κάθε πρώτο Σάββατο""κάθε δεύτερο Σάββατο""κάθε τρίτο Σάββατο""κάθε τέταρτο Σάββατο""κάθε προηγούμενο Σάββατο"
================================================
FILE: library/src/main/res/values-el/strings.xml
================================================
"Αποστολή μηνύματος ηλεκτρονικού ταχυδρομείου με""Τέλος""Επανάληψη""Δεν επαναλαμβάνεται""Κάθε %d ημέρα""Κάθε %d ημέρες""Κάθε %d εβδομάδα""Κάθε %d εβδομάδες""Κάθε %d μήνα""Κάθε %d μήνες""Κάθε %d έτος""Κάθε %d έτη""ίδια ημέρα κάθε μήνα""Για πάντα""Μέχρι μια ορισμένη ημ/νία""Έως τις %s""Για έναν αριθμό συμβάντων""Για %d συμβάν""Για %d συμβάντα""αλλαγή ημερομηνίας λήξης"
================================================
FILE: library/src/main/res/values-en-rGB/arrays.xml
================================================
"Notification""Email""SMS""Alarm""0 minutes""1 minute""5 minutes""10 minutes""15 minutes""20 minutes""25 minutes""30 minutes""45 minutes""1 hour""2 hours""3 hours""12 hours""24 hours""2 days""1 week""None""0 minutes""1 minute""5 minutes""10 minutes""15 minutes""20 minutes""25 minutes""30 minutes""45 minutes""1 hour""2 hours""3 hours""12 hours""24 hours""2 days""1 week""Locale default""Saturday""Sunday""Monday""Busy""Available""Tentative""Default""Private""Public""first""second""third""fourth""last""No response""Yes"" Maybe""No""Only this event""This and future events""All events""This & future events""All events""Only this event""All events in the series""Day""Week""Month""Agenda""Only if declined""If declined or not responded""REPEAT DAILY""REPEAT WEEKLY""REPEAT MONTHLY""REPEAT YEARLY""on every first Sunday""on every second Sunday""on every third Sunday""on every fourth Sunday""on every last Sunday""on every first Monday""on every second Monday""on every third Monday""on every fourth Monday""on every last Monday""on every first Tuesday""on every second Tuesday""on every third Tuesday""on every fourth Tuesday""on every last Tuesday""on every first Wednesday""on every second Wednesday""on every third Wednesday""on every fourth Wednesday""on every last Wednesday""on every first Thursday""on every second Thursday""on every third Thursday""on every fourth Thursday""on every last Thursday""on every first Friday""on every second Friday""on every third Friday""on every fourth Friday""on every last Friday""on every first Saturday""on every second Saturday""on every third Saturday""on every fourth Saturday""on every last Saturday"
================================================
FILE: library/src/main/res/values-en-rGB/strings.xml
================================================
"Email with""Done""Snooze all""Dismiss all""Snooze""One-time event""; until %s""; for one time""; for %d times""Daily""Every %d days""Every weekday (Mon–Fri)""Weekly on %2$s""Every %1$d weeks on %2$s""Monthly""Yearly""Monthly (on day %s)""Yearly (on %s)""Repeat""Never repeats""Every %d day""Every %d days""Every %d week""Every %d weeks""Every %d month""Every %d months""Every %d year""Every %d years""on the same day each month""Forever""Until a date""Until %s""For a number of events""For %d event""For %d events""change end date"
================================================
FILE: library/src/main/res/values-es/arrays.xml
================================================
"Notificación""Correo""SMS""Alarma""0 minutos""1 minuto""5 minutos""10 minutos""15 minutos""20 minutos""25 minutos""30 minutos""45 minutos""1 hora""2 horas""3 horas""12 horas""24 horas""2 días""1 semana""Ninguno""0 minutos""1 minuto""5 minutos""10 minutos""15 minutos""20 minutos""25 minutos""30 minutos""45 minutos""1 hora""2 horas""3 horas""12 horas""24 horas""2 días""1 semana""Región predeterminada""Sábado""Domingo""Lunes""Ocupado""Disponible""Provisional""Predeterminado""Privado""Público""primer""segundo""tercer""cuarto""último""Sin respuesta""Sí""Quizás""No""Solo este evento""Este y otros eventos posteriores""Todos los eventos""Este y otros eventos posteriores""Todos los eventos""Solo este evento""Todos los eventos de la serie""Día""Semana""Mes""Agenda""Solo si se rechaza""Si se rechaza o no responde""REPETIR DIARIAMENTE""REPETIR SEMANALMENTE""REPETIR MENSUALMENTE""REPETIR ANUALMENTE""cada primer domingo del mes""cada segundo domingo del mes""cada tercer domingo del mes""cada cuarto domingo del mes""cada último domingo del mes""cada primer lunes del mes""cada segundo lunes del mes""cada tercer lunes del mes""cada cuarto lunes del mes""cada último lunes del mes""cada primer martes del mes""cada segundo martes del mes""cada tercer martes del mes""cada cuarto martes del mes""cada último martes del mes""cada primer miércoles del mes""cada segundo miércoles del mes""cada tercer miércoles del mes""cada cuarto miércoles del mes""cada último miércoles del mes""cada primer jueves del mes""cada segundo jueves del mes""cada tercer jueves del mes""cada cuarto jueves del mes""cada último jueves del mes""cada primer viernes del mes""cada segundo viernes del mes""cada tercer viernes del mes""cada cuarto viernes del mes""cada último viernes del mes""cada primer sábado del mes""cada segundo sábado del mes""cada tercer sábado del mes""cada cuarto sábado del mes""cada último sábado del mes"
================================================
FILE: library/src/main/res/values-es/strings.xml
================================================
"Correo electrónico con""Listo""Repetir""No se repite""Cada %d día""Cada %d días""Cada %d semana""Cada %d semanas""Cada %d mes""Cada %d meses""Cada %d año""Cada %d años""el mismo día de cada mes""Siempre""Hasta una fecha""Hasta el %s""Para un número de eventos""Para %d evento""Para %d eventos""cambiar fecha de finalización"
================================================
FILE: library/src/main/res/values-es-rUS/arrays.xml
================================================
"Notificación""Correo""SMS""Alarma""0 minutos""1 minuto""5 minutos""10 minutos""15 minutos""20 minutos""25 minutos""30 minutos""45 minutos""1 hora""2 horas""3 horas""12 horas""24 horas""2 días""1 semana""Ninguno""0 minutos""1 minuto""5 minutos""10 minutos""15 minutos""20 minutos""25 minutos""30 minutos""45 minutos""1 hora""2 horas""3 horas""12 horas""24 horas""2 días""1 semana""Configuración regional predeterminada""Sábado""Domingo""Lunes""No disponible""Disponible""Provisional""Predeterminado""Privado""Público""primer""segundo""tercer""cuarto""último""Sin respuesta""Sí""Tal vez""No""Sólo este evento""Este y futuros eventos""Todos los eventos""Este y eventos futuros""Todos los eventos""Solo este evento""Todos los eventos en la serie""Día""Semana""Mes""Agenda""Solo si se rechaza""Si se rechaza o no tiene respuesta""REPETIR DIARIAMENTE""REPETIR SEMANALMENTE""REPETIR MENSUALMENTE""REPETIR ANUALMENTE""cada primer domingo del mes""cada segundo domingo del mes""cada tercer domingo del mes""cada cuarto domingo del mes""cada último domingo del mes""cada primer lunes del mes""cada segundo lunes del mes""cada tercer lunes del mes""cada cuarto lunes del mes""cada último lunes del mes""cada primer martes del mes""cada segundo martes del mes""cada tercer martes del mes""cada cuarto martes del mes""cada último martes del mes""cada primer miércoles del mes""cada segundo miércoles del mes""cada tercer miércoles del mes""cada cuarto miércoles del mes""cada último miércoles del mes""cada primer jueves del mes""cada segundo jueves del mes""cada tercer jueves del mes""cada cuarto jueves del mes""cada último jueves del mes""cada primer viernes del mes""cada segundo viernes del mes""cada tercer viernes del mes""cada cuarto viernes del mes""cada último viernes del mes""cada primer sábado del mes""cada segundo sábado del mes""cada tercer sábado del mes""cada cuarto sábado del mes""cada último sábado del mes"
================================================
FILE: library/src/main/res/values-es-rUS/strings.xml
================================================
"Enviar correo a""Finalizar""Repetir""No se repite""Cada %d día""Cada %d días""Cada %d semana""Cada %d semanas""Cada %d mes""Cada %d meses""Cada %d año""Cada %d años""el mismo día cada mes""Siempre""Hasta una fecha""Hasta %s""En ciertos eventos""En %d evento""En %d eventos""cambiar la fecha final"
================================================
FILE: library/src/main/res/values-et/arrays.xml
================================================
"Teatis""E-post""SMS""Alarm""0 minutit""1 minut""5 minutit""10 minutit""15 minutit""20 minutit""25 minutit""30 minutit""45 minutit""1 tund""2 tundi""3 tundi""12 tundi""24 tundi""2 päeva""1 nädal""Puudub""0 minutit""1 minut""5 minutit""10 minutit""15 minutit""20 minutit""25 minutit""30 minutit""45 minutit""1 tund""2 tundi""3 tundi""12 tundi""24 tundi""2 päeva""1 nädal""Lokaadi vaikeseade""Laupäev""Pühapäev""Esmaspäev""Hõivatud""Saadaval""Katseline""Vaikeseade""Privaatne""Avalik""esimene""sekund""kolmas""neljas""viimane""Vastust pole""Jah""Võib-olla""Ei""Ainult see sündmus""See sündmus ja tulevased sündmused""Kõik sündmused""See ja tulevased sündmused""Kõik sündmused""Ainult see sündmus""Kõik seerias olevad sündmused""Päev""Nädal""Kuu""Ajakava""Ainult keeldumisel""Keeldumisel või vastamata jätmisel""KORDA IGA PÄEV""KORDA IGAL NÄDALAL""KORDA IGAS KUUS""KORDA IGAL AASTAL""iga kuu esimesel pühapäeval""iga kuu teisel pühapäeval""iga kuu kolmandal pühapäeval""iga kuu neljandal pühapäeval""iga kuu viimasel pühapäeval""iga kuu esimesel esmaspäeval""iga kuu teisel esmaspäeval""iga kuu kolmandal esmaspäeval""iga kuu neljandal esmaspäeval""iga kuu viimasel esmaspäeval""iga kuu esimesel teisipäeval""iga kuu teisel teisipäeval""iga kuu kolmandal teisipäeval""iga kuu neljandal teisipäeval""iga kuu viimasel teisipäeval""iga kuu esimesel kolmapäeval""iga kuu teisel kolmapäeval""iga kuu kolmandal kolmapäeval""iga kuu neljandal kolmapäeval""iga kuu viimasel kolmapäeval""iga kuu esimesel neljapäeval""iga kuu teisel neljapäeval""iga kuu kolmandal neljapäeval""iga kuu neljandal neljapäeval""iga kuu viimasel neljapäeval""iga kuu esimesel reedel""iga kuu teisel reedel""iga kuu kolmandal reedel""iga kuu neljandal reedel""iga kuu viimasel reedel""iga kuu esimesel laupäeval""iga kuu teisel laupäeval""iga kuu kolmandal laupäeval""iga kuu neljandal laupäeval""iga kuu viimasel laupäeval"
================================================
FILE: library/src/main/res/values-et/strings.xml
================================================
"Meili saatmine:""Valmis""Kordamine""Ei kordu kunagi""Iga %d päeva tagant""Iga %d päeva tagant""Iga %d nädala tagant""Iga %d nädala tagant""Iga %d kuu tagant""Iga %d kuu tagant""Iga %d aasta tagant""Iga %d aasta tagant""iga kuu samal päeval""Igavesti""Kuni kuupäevani""Kuni %s""Sündmust korratakse""%d sündmuse puhul""%d sündmuse puhul""lõppkuupäeva muutmine"
================================================
FILE: library/src/main/res/values-fa/arrays.xml
================================================
"اعلان""ایمیل""پیامک""زنگ هشدار""0 دقیقه""۱ دقیقه""۵ دقیقه""۱۰ دقیقه""۱۵ دقیقه""۲۰ دقیقه""۲۵ دقیقه""۳۰ دقیقه""۴۵ دقیقه""۱ ساعت""۲ ساعت""۳ ساعت""۱۲ ساعت""۲۴ ساعت""۲ روز""۱ هفته""هیچکدام""0 دقیقه""۱ دقیقه""۵ دقیقه""۱۰ دقیقه""۱۵ دقیقه""۲۰ دقیقه""۲۵ دقیقه""۳۰ دقیقه""۴۵ دقیقه""۱ ساعت""۲ ساعت""۳ ساعت""۱۲ ساعت""۲۴ ساعت""۲ روز""۱ هفته""پیشفرض محلی""شنبه""یکشنبه""دوشنبه""مشغول""موجود""احتمالی""پیشفرض""خصوصی""عمومی""ابتدا""ثانیه""سومین""چهارمین""آخرین""بدون پاسخ""بله""شاید""خیر""فقط این رویداد""این رویداد و رویدادهای آینده""همه رویدادها""این و رویدادهای آینده""همه رویدادها""فقط این رویداد""همه رویدادهای موجود در این مجموعه""روز""هفته""ماه""دستور جلسه""فقط درصورت ردکردن""درصورت ردکردن یا پاسخ ندادن""تکرار روزانه""تکرار هفتگی""تکرار ماهانه""تکرار سالانه""اولین یکشنبه هر ماه""دومین یکشنبه هر ماه""سومین یکشنبه هر ماه""چهارمین یکشنبه هر ماه""آخرین یکشنبه هر ماه""اولین دوشنبه هر ماه""دومین دوشنبه هر ماه""سومین دوشنبه هر ماه""چهارمین دوشنبه هر ماه""آخرین دوشنبه هر ماه""اولین سهشنبه هر ماه""دومین سهشنبه هر ماه""سومین سهشنبه هر ماه""چهارمین سهشنبه هر ماه""آخرین سهشنبه هر ماه""اولین چهارشنبه هر ماه""دومین چهارشنبه هر ماه""سومین چهارشنبه هر ماه""چهارمین چهارشنبه هر ماه""آخرین چهارشنبه هر ماه""اولین پنجشنبه هر ماه""دومین پنجشنبه هر ماه""سومین پنجشنبه هر ماه""چهارمین پنجشنبه هر ماه""آخرین پنجشنبه هر ماه""اولین جمعه هر ماه""دومین جمعه هر ماه""سومین جمعه هر ماه""چهارمین جمعه هر ماه""آخرین جمعه هر ماه""اولین شنبه هر ماه""دومین شنبه هر ماه""سومین شنبه هر ماه""چهارمین شنبه هر ماه""آخرین شنبه هر ماه"
================================================
FILE: library/src/main/res/values-fa/strings.xml
================================================
"ایمیل با""انجام شد""تکرار""هرگز تکرار نمیشود""هر %d روز""هر %d روز""هر %d هفته""هر %d هفته""هر %d ماه""هر %d ماه""هر %d سال""هر %d سال""در یک روز معین از هر ماه""همیشه""تا یک تاریخ معین""تا %s""برای تعدادی از رویدادها""برای %d رویداد""برای %d رویداد""تغییر تاریخ پایان"
================================================
FILE: library/src/main/res/values-fi/arrays.xml
================================================
"Ilmoitus""Sähköposti""Tekstiviesti""Hälytys""0 minuuttia""1 minuutti""5 minuuttia""10 minuuttia""15 minuuttia""20 minuuttia""25 minuuttia""30 minuuttia""45 minuuttia""1 tunti""2 tuntia""3 tuntia""12 tuntia""24 tuntia""2 päivää""1 viikko""Ei mitään""0 minuuttia""1 minuutti""5 minuuttia""10 minuuttia""15 minuuttia""20 minuuttia""25 minuuttia""30 minuuttia""45 minuuttia""1 tunti""2 tuntia""3 tuntia""12 tuntia""24 tuntia""2 päivää""1 viikko""Oletussijainti""lauantai""sunnuntai""maanantai""Varattu""Tavoitettavissa""Alustava""Oletus""Yksityinen""Julkinen""ensimmäinen""sekunti""kolmas""neljäs""viimeinen""Ei vastausta""Kyllä""Ehkä""Ei""Vain tämä tapahtuma""Tämä ja tulevat tapahtumat""Kaikki tapahtumat""Tämä ja tulevat tapahtumat""Kaikki tapahtumat""Vain tämä tapahtuma""Kaikki toistokerrat""Päivä""Viikko""Kuukausi""Tapahtumat""Vain jos kieltäydyn""Jos kieltäydyn tai en vastaa""TOISTA PÄIVITTÄIN""TOISTA VIIKOITTAIN""TOISTA KUUKAUSITTAIN""TOISTA VUOSITTAIN""kuukauden 1. sunnuntai""kuukauden 2. sunnuntai""kuukauden 3. sunnuntai""kuukauden 4. sunnuntai""kuukauden viimeinen sunnuntai""kuukauden 1. maanantai""kuukauden 2. maanantai""kuukauden 3. maanantai""kuukauden 4. maanantai""kuukauden viimeinen maanantai""kuukauden 1. tiistai""kuukauden 2. tiistai""kuukauden 3. tiistai""kuukauden 4. tiistai""kuukauden viimeinen tiistai""kuukauden 1. keskiviikko""kuukauden 2. keskiviikko""kuukauden 3. keskiviikko""kuukauden 4. keskiviikko""kuukauden viim. keskiviikko""kuukauden 1. torstai""kuukauden 2. torstai""kuukauden 3. torstai""kuukauden 4. torstai""kuukauden viimeinen torstai""kuukauden 1. perjantai""kuukauden 2. perjantai""kuukauden 3. perjantai""kuukauden 4. perjantai""kuukauden viimeinen perjantai""kuukauden 1. lauantai""kuukauden 2. lauantai""kuukauden 3. lauantai""kuukauden 4. lauantai""kuukauden viimeinen lauantai"
================================================
FILE: library/src/main/res/values-fi/strings.xml
================================================
"Sähköposti ja""Valmis""Toisto""Ei toistu""%d päivän välein""%d päivän välein""%d viikon välein""%d viikon välein""%d kuukauden välein""%d kuukauden välein""%d vuoden välein""%d vuoden välein""samana päiv. joka kk""Ikuisesti""Tiettyyn päivään saakka""%s saakka""Useita kertoja""%d tapahtuman ajan""%d tapahtuman ajan""muuta lopetuspäivää"
================================================
FILE: library/src/main/res/values-fr/arrays.xml
================================================
"Notification""E-mail""SMS""Alarme""0 minute""1 minute""5 minutes""10 minutes""15 minutes""20 minutes""25 minutes""30 minutes""45 minutes""1 heure""2 heures""3 heures""12 heures""24 heures""2 jours""1 semaine""Aucun""0 minute""1 minute""5 minutes""10 minutes""15 minutes""20 minutes""25 minutes""30 minutes""45 minutes""1 heure""2 heures""3 heures""12 heures""24 heures""2 jours""1 semaine""Paramètres régionaux par défaut""Samedi""Dimanche""Lundi""Occupé""Disponible""À confirmer""Par défaut""Privé""Public""1er""2e""3e""4e""dernier""Aucune réponse""Oui""Peut-être""Non""Uniquement cet événement""Cet événement et les suivants""Tous les événements""Cet événement et les suivants""Tous les événements""Uniquement cet événement""Tous les événements de la série""Jour""Semaine""Mois""Planning""Seulement en cas de refus""Si refus ou pas de réponse""TOUS LES JOURS""TOUTES LES SEMAINES""TOUS LES MOIS""TOUS LES ANS""tous les premiers dimanches""tous les deuxièmes dimanches""tous les troisièmes dimanches""tous les quatrièmes dimanches""tous les derniers dimanches""tous les premiers lundis""tous les deuxièmes lundis""tous les troisièmes lundis""tous les quatrièmes lundis""tous les derniers lundis""tous les premiers mardis""tous les deuxièmes mardis""tous les troisièmes mardis""tous les quatrièmes mardis""tous les derniers mardis""tous les premiers mercredis""tous les deuxièmes mercredis""tous les troisièmes mercredis""tous les quatrièmes mercredis""tous les derniers mercredis""tous les premiers jeudis""tous les deuxièmes jeudis""tous les troisièmes jeudis""tous les quatrièmes jeudis""tous les derniers jeudis""tous les premiers vendredis""tous les deuxièmes vendredis""tous les troisièmes vendredis""tous les quatrièmes vendredis""tous les derniers vendredis""tous les premiers samedis""tous les deuxièmes samedis""tous les troisièmes samedis""tous les quatrièmes samedis""tous les derniers samedis"
================================================
FILE: library/src/main/res/values-fr/strings.xml
================================================
"Envoyer un e-mail via""OK""Tout répéter""Tout supprimer""Répéter""Événement ponctuel""; jusqu\'au %s""; une seule fois""; %d fois""Quotidien""Tous les %d jours""Jours ouvrés (lun–ven)""Hebdomadaire (le %2$s)""Toutes les %1$d semaines le %2$s""Tous les mois""Tous les ans""Mensuel (le %s)""Annuel (le %s)""Répéter""Ne jamais répéter""Tous les %d jour""Tous les %d jours""Toutes les %d semaine""Toutes les %d semaines""Tous les %d mois""Tous les %d mois""Tous les %d an""Tous les %d ans""le même jour chaque mois""Toujours""Jusqu\'à une certaine date""Jusqu\'au %s""Pour une série d\'événements""Pour %d événement""Pour %d événements""modifier la date de fin"
================================================
FILE: library/src/main/res/values-hi/arrays.xml
================================================
"सूचना""ईमेल""SMS""अलार्म""0 मिनट""1 मिनट""5 मिनट""10 मिनट""15 मिनट""20 मिनट""25 मिनट""30 मिनट""45 मिनट""1 घंटा""2 घंटे""3 घंटे""12 घंटे""24 घंटे""2 दिन""1 सप्ताह""कोई नहीं""0 मिनट""1 मिनट""5 मिनट""10 मिनट""15 मिनट""20 मिनट""25 मिनट""30 मिनट""45 मिनट""1 घंटा""2 घंटे""3 घंटे""12 घंटे""24 घंटे""2 दिन""1 सप्ताह""स्थान डिफ़ॉल्ट""शनिवार""रविवार""सोमवार""व्यस्त""उपलब्ध""अस्थायी""डिफ़ॉल्ट""निजी""सार्वजनिक""पहला""सेकंड""तीसरा""चौथा""अंतिम""कोई प्रतिसाद नहीं""हां"" शायद""नहीं""केवल यह ईवेंट""यह और आगामी ईवेंट""सभी ईवेंट""यह और भविष्य के ईवेंट""सभी ईवेंट""केवल यह ईवेंट""श्रृंखला में सभी ईवेंट""दिन""सप्ताह""माह""कार्यसूची""केवल अस्वीकार होने पर""यदि अस्वीकार हुआ हो या जवाब न मिला हो""हर दिन दोहराएं""हर सप्ताह दोहराएं""हर माह दोहराएं""हर वर्ष दोहराएं""प्रत्येक पहले रविवार को""प्रत्येक दूसरे रविवार को""प्रत्येक तीसरे रविवार को""प्रत्येक चौथे रविवार को""प्रत्येक अंतिम रविवार को""प्रत्येक पहले सोमवार को""प्रत्येक दूसरे सोमवार को""प्रत्येक तीसरे सोमवार को""प्रत्येक चौथे सोमवार को""प्रत्येक अंतिम सोमवार को""प्रत्येक पहले मंगलवार को""प्रत्येक दूसरे मंगलवार को""प्रत्येक तीसरे मंगलवार को""प्रत्येक चौथे मंगलवार को""प्रत्येक अंतिम मंगलवार को""प्रत्येक पहले बुधवार को""प्रत्येक दूसरे बुधवार को""प्रत्येक तीसरे बुधवार को""प्रत्येक चौथे बुधवार को""प्रत्येक अंतिम बुधवार को""प्रत्येक पहले गुरुवार को""प्रत्येक दूसरे गुरुवार को""प्रत्येक तीसरे गुरुवार को""प्रत्येक चौथे गुरुवार को""प्रत्येक अंतिम गुरुवार को""प्रत्येक पहले शुक्रवार को""प्रत्येक दूसरे शुक्रवार को""प्रत्येक तीसरे शुक्रवार को""प्रत्येक चौथे शुक्रवार को""प्रत्येक अंतिम शुक्रवार को""प्रत्येक पहले शनिवार को""प्रत्येक दूसरे शनिवार को""प्रत्येक तीसरे शनिवार को""प्रत्येक चौथे शनिवार को""प्रत्येक अंतिम शनिवार को"
================================================
FILE: library/src/main/res/values-hi/strings.xml
================================================
"इन्हें ईमेल करें""पूर्ण""दोहराएं""कभी न दोहराएं""प्रत्येक %d दिन में""प्रत्येक %d दिन में""प्रत्येक %d सप्ताह में""प्रत्येक %d सप्ताह में""प्रत्येक %d माह में""प्रत्येक %d माह में""प्रत्येक %d वर्ष में""प्रत्येक %d वर्ष में""प्रत्येक माह उसी दिन""हमेशा""इस दिनांक तक""%s तक""कई ईवेंट के लिए""%d ईवेंट के लिए""%d ईवेंट के लिए""समाप्ति दिनांक बदलें"
================================================
FILE: library/src/main/res/values-hr/arrays.xml
================================================
"Obavijest""E-pošta""SMS""Alarm""0 minuta""1 minuta""5 minuta""10 minuta""15 minuta""20 minuta""25 minuta""30 minuta""45 minuta""1 sat""2 sata""3 sata""12 sati""24 sata""2 dana""1 tjedan""Ništa""0 minuta""1 minuta""5 minuta""10 minuta""15 minuta""20 minuta""25 minuta""30 minuta""45 minuta""1 sat""2 sata""3 sata""12 sati""24 sata""2 dana""1 tjedan""Zadana oznaka zemlje""Subota""Nedjelja""Ponedjeljak""Zauzet""Dostupan""Privremena""Zadano""Privatno""Javno""prvo""drugi""treće""četvrto""posljednje""Nema odgovora""Da""Možda""Ne""Samo ovaj događaj""Ovaj i budući događaji""Svi događaji""Ovaj i budući događaji""Svi događaji""Samo ovaj događaj""Svi događaji u nizu""Dan""Tjedan""Mjesec""Raspored""Samo ako je odbijeno""Ako je odbijeno ili nema odgovora""DNEVNO PONAVLJANJE""PONAVLJAJ TJEDNO""PONAVLJAJ MJESEČNO""PONAVLJAJ GODIŠNJE""svake prve nedjelje""svake druge nedjelje""svake treće nedjelje""svake četvrte nedjelje""svake zadnje nedjelje""svakog prvog ponedjeljka""svakog drugog ponedjeljka""svakog trećeg ponedjeljka""svakog četvrtog ponedjeljka""svakog zadnjeg ponedjeljka""svakog prvog utorka""svakog drugog utorka""svakog trećeg utorka""svakog četvrtog utorka""svakog zadnjeg utorka""svake prve srijede""svake druge srijede""svake treće srijede""svake četvrte srijede""svake zadnje srijede""svakog prvog četvrtka""svakog drugog četvrtka""svakog trećeg četvrtka""svakog četvrtog četvrtka""svakog zadnjeg četvrtka""svakog prvog petka""svakog drugog petka""svakog trećeg petka""svakog četvrtog petka""svakog zadnjeg petka""svake prve subote""svake druge subote""svake treće subote""svake četvrte subote""svake zadnje subote"
================================================
FILE: library/src/main/res/values-hr/strings.xml
================================================
"Obavijesti e-poštom""Gotovo""Ponovi""Ne ponavlja se nikad""Svakog %d. dana""Svakog %d. dana""Svakog %d. tjedna""Svakog %d. tjedna""Svakog %d. mjeseca""Svakog %d. mjeseca""Svake %d. godine""Svake %d. godine""na isti dan svakog mjeseca""Zauvijek""Do datuma""Do %s""Za ovoliko događaja""Za ovoliko događaja: %d""Za ovoliko događaja: %d""promjena datuma završetka"
================================================
FILE: library/src/main/res/values-hu/arrays.xml
================================================
"Értesítés""E-mail""SMS""Ébresztő""0 perc""1 perc""5 perc""10 perc""15 perc""20 perc""25 perc""30 perc""45 perc""1 óra""2 óra""3 óra""12 óra""24 óra""2 nap""1 hét""Semelyik""0 perc""1 perc""5 perc""10 perc""15 perc""20 perc""25 perc""30 perc""45 perc""1 óra""2 óra""3 óra""12 óra""24 óra""2 nap""1 hét""Helyi alapértelmezett""Szombat""Vasárnap""Hétfő""Elfoglalt""Elérhető""Kísérleti""Alapértelmezett""Privát""Nyilvános""első""másodperc""harmadik""negyedik""utolsó""Nincs válasz""Igen""Lehet""Nem""Csak a jelenlegi esemény""A jelen és a jövőbeli események""Összes esemény""A jelenlegi és a további események""Összes esemény""Csak a jelen esemény""A sorozat összes eseményére""Nap""Hét""Hónap""Napló""Csak elutasítás esetén""Elutasítás/nem válaszolás esetén""ISMÉTLÉS NAPONTA""ISMÉTLÉS HETENTE""ISMÉTLÉS HAVONTA""ISMÉTLÉS ÉVENTE""minden első vasárnapon""minden második vasárnapon""minden harmadik vasárnapon""minden negyedik vasárnapon""minden utolsó vasárnapon""minden első hétfőn""minden második hétfőn""minden harmadik hétfőn""minden negyedik hétfőn""minden utolsó hétfőn""minden első kedden""minden második kedden""minden harmadik kedden""minden negyedik kedden""minden utolsó kedden""minden első szerdán""minden második szerdán""minden harmadik szerdán""minden negyedik szerdán""minden utolsó szerdán""minden első csütörtökön""minden második csütörtökön""minden harmadik csütörtökön""minden negyedik csütörtökön""minden utolsó csütörtökön""minden első pénteken""minden második pénteken""minden harmadik pénteken""minden negyedik pénteken""minden utolsó pénteken""minden első szombaton""minden második szombaton""minden harmadik szombaton""minden negyedik szombaton""minden utolsó szombaton"
================================================
FILE: library/src/main/res/values-hu/strings.xml
================================================
"E-mail a következővel:""Kész""Ismétlődés""Soha nem ismétli""%d naponta""%d naponta""%d hetente""%d hetente""%d havonta""%d havonta""%d évente""%d évente""havonta ugyanakkor""Végtelenszer""Meghatározott dátumig""Záró dátum: %s""Adott számú alkalommal""%d eseményhez""%d eseményhez""befejezés dátumának módosítása"
================================================
FILE: library/src/main/res/values-in/arrays.xml
================================================
"Pemberitahuan""Email""SMS""Alarm""0 menit""1 menit""5 menit""10 menit""15 menit""20 menit""25 menit""30 menit""45 menit""1 jam""2 jam""3 jam""12 jam""24 jam""2 hari""1 minggu""Tak Satu Pun""0 menit""1 menit""5 menit""10 menit""15 menit""20 menit""25 menit""30 menit""45 menit""1 jam""2 jam""3 jam""12 jam""24 jam""2 hari""1 minggu""Lokal default""Sabtu""Minggu""Senin""Sibuk""Tersedia""Sementara""Default""Pribadi""Umum""pertama""kedua""ketiga""keempat""terakhir""Tidak ada tanggapan""Ya""Mungkin""Tidak""Hanya acara ini""Acara saat ini dan di masa mendatang""Semua acara""Acara & mendatang ini""Semua acara""Hanya acara ini""Semua acara dalam rangkaian""Hari""Minggu""Bulan""Agenda""Hanya jika ditolak""Jika ditolak atau tidak ditanggapi""PENGULANGAN HARIAN""PENGULANGAN MINGGUAN""PENGULANGAN BULANAN""PENGULANGAN TAHUNAN""setiap Minggu pertama""setiap Minggu kedua""setiap Minggu ketiga""setiap Minggu keempat""setiap Minggu terakhir""setiap Senin pertama""setiap Senin kedua""setiap Senin ketiga""setiap Senin keempat""setiap Senin terakhir""setiap Selasa pertama""setiap Selasa kedua""setiap Selasa ketiga""setiap Selasa keempat""setiap Selasa terakhir""setiap Rabu pertama""setiap Rabu kedua""setiap Rabu ketiga""setiap Rabu keempat""setiap Rabu terakhir""setiap Kamis pertama""setiap Kamis kedua""setiap Kamis ketiga""setiap Kamis keempat""setiap Kamis terakhir""setiap Jumat pertama""setiap Jumat kedua""setiap Jumat ketiga""setiap Jumat keempat""setiap Jumat terakhir""setiap Sabtu pertama""setiap Sabtu kedua""setiap Sabtu ketiga""setiap Sabtu keempat""setiap Sabtu terakhir"
================================================
FILE: library/src/main/res/values-in/strings.xml
================================================
"Email dengan""Selesai""Ulangi""Jangan diulang""%d hari sekali""%d hari sekali""%d minggu sekali""%d minggu sekali""%d bulan sekali""%d bulan sekali""%d tahun sekali""%d tahun sekali""bulanan-hari yg sama""Selamanya""Sampai tanggal tertentu""Sampai %s""Untuk sejumlah acara""Untuk %d acara""Untuk %d acara""ubah tanggal akhir"
================================================
FILE: library/src/main/res/values-it/arrays.xml
================================================
"Notifica""Email""SMS""Allarme""0 minuti""1 minuto""5 minuti""10 minuti""15 minuti""20 minuti""25 minuti""30 minuti""45 minuti""1 ora""2 ore""3 ore""12 ore""24 ore""2 giorni""1 settimana""Nessuno""0 minuti""1 minuto""5 minuti""10 minuti""15 minuti""20 minuti""25 minuti""30 minuti""45 minuti""1 ora""2 ore""3 ore""12 ore""24 ore""2 giorni""1 settimana""Impostazioni internazionali predefinite""Sabato""Domenica""Lunedì""Occupato""Disponibile""Tentativo""Predefinito""Privato""Pubblico""primo""secondo""terzo""quarto""ultimo""Nessuna risposta""Sì""Forse""No""Solo questo evento""Questo e gli eventi futuri""Tutti gli eventi""Questo e gli eventi futuri""Tutti gli eventi""Solo questo evento""Tutti gli eventi nella serie""Giorno""Settimana""Mese""Ordine del giorno""Solo se rifiutati""Se rifiutati o senza risposta""GIORNALIERA""SETTIMANALE""MENSILE""ANNUALE""ogni prima domenica""ogni seconda domenica""ogni terza domenica""ogni quarta domenica""ogni ultima domenica""ogni primo lunedì""ogni secondo lunedì""ogni terzo lunedì""ogni quarto lunedì""ogni ultimo lunedì""ogni primo martedì""ogni secondo martedì""ogni terzo martedì""ogni quarto martedì""ogni ultimo martedì""ogni primo mercoledì""ogni secondo mercoledì""ogni terzo mercoledì""ogni quarto mercoledì""ogni ultimo mercoledì""ogni primo giovedì""ogni secondo giovedì""ogni terzo giovedì""ogni quarto giovedì""ogni ultimo giovedì""ogni primo venerdì""ogni secondo venerdì""ogni terzo venerdì""ogni quarto venerdì""ogni ultimo venerdì""ogni primo sabato""ogni secondo sabato""ogni terzo sabato""ogni quarto sabato""ogni ultimo sabato"
================================================
FILE: library/src/main/res/values-it/strings.xml
================================================
"Invia email con""Salva""Ripeti""Nessuna ripetizione""Ogni %d giorni""Ogni %d giorni""Ogni %d settimana""Ogni %d settimane""Ogni %d mesi""Ogni %d mesi""Ogni %d anni""Ogni %d anni""lo stesso giorno ogni mese""Sempre""Fino a una data""Fino al giorno: %s""Per una serie di eventi""Per %d evento""Per %d eventi""modifica data di fine"
================================================
FILE: library/src/main/res/values-iw/arrays.xml
================================================
"התראה""דוא\"ל""SMS""התראה""0 דקות""דקה אחת""5 דקות""10 דקות""15 דקות""20 דקות""25 דקות""30 דקות""45 דקות""שעה אחת""שעתיים""3 שעות""12 שעות""24 שעות""יומיים""שבוע אחד""ללא""0 דקות""דקה אחת""5 דקות""10 דקות""15 דקות""20 דקות""25 דקות""30 דקות""45 דקות""שעה אחת""שעתיים""3 שעות""12 שעות""24 שעות""יומיים""שבוע אחד""ברירת מחדל של מיקום""יום שבת""יום ראשון""יום שני""לא פנוי""זמין""לא סופי""ברירת מחדל""פרטי""ציבורי""ראשון""שני""שלישי""רביעי""אחרון""אין תגובה""כן""אולי""לא""רק אירוע זה""אירוע זה ואירועים עתידיים""כל האירועים""אירוע זה ואירועים עתידיים""כל האירועים""אירוע זה בלבד""כל האירועים בסדרה""יום""שבוע""חודש""סדר יום""רק לאחר הבעת סירוב""לאחר הבעת סירוב או אם אין תגובה""חזרה על בסיס יומי""חזרה על בסיס שבועי""חזרה על בסיס חודשי""חזרה על בסיס שנתי""בכל יום ראשון הראשון בכל חודש""בכל יום ראשון השני בכל חודש""בכל יום ראשון השלישי בכל חודש""בכל יום ראשון הרביעי בכל חודש""בכל יום ראשון האחרון בכל חודש""בכל יום שני הראשון בכל חודש""בכל יום שני השני בכל חודש""בכל יום שני השלישי בכל חודש""בכל יום שני הרביעי בכל חודש""בכל יום שני האחרון בכל חודש""בכל יום שלישי הראשון בכל חודש""בכל יום שלישי השני בכל חודש""בכל יום שלישי השלישי בכל חודש""בכל יום שלישי הרביעי בכל חודש""בכל יום שלישי האחרון בכל חודש""בכל יום רביעי הראשון בכל חודש""בכל יום רביעי השני בכל חודש""בכל יום רביעי השלישי בכל חודש""בכל יום רביעי הרביעי בכל חודש""בכל יום רביעי האחרון בכל חודש""בכל יום חמישי הראשון בכל חודש""בכל יום חמישי השני בכל חודש""בכל יום חמישי השלישי בכל חודש""בכל יום חמישי הרביעי בכל חודש""בכל יום חמישי האחרון בכל חודש""בכל יום שישי הראשון בכל חודש""בכל יום שישי השני בכל חודש""בכל יום שישי השלישי בכל חודש""בכל יום שישי הרביעי בכל חודש""בכל יום שישי האחרון בכל חודש""בכל יום שבת הראשון בכל חודש""בכל יום שבת השני בכל חודש""בכל יום שבת השלישי בכל חודש""בכל יום שבת הרביעי בכל חודש""בכל יום שבת האחרון בכל חודש"
================================================
FILE: library/src/main/res/values-iw/strings.xml
================================================
"שלח הודעת דוא\"ל באמצעות""סיום""חזרה""ללא חזרה""כל יום %d""כל %d ימים""כל שבוע %d""כל %d שבועות""כל חודש %d""כל %d חודשים""כל שנה %d""כל %d שנים""באותו יום בכל חודש""ללא תאריך סיום""עד תאריך מסוים""עד %s""למספר אירועים""עבור אירוע %d""עבור %d אירועים""שינוי של תאריך הסיום"
================================================
FILE: library/src/main/res/values-ja/arrays.xml
================================================
"通知""メール""SMS""アラーム""0分""1分""5分""10分""15分""20分""25分""30分""45分""1時間""2時間""3時間""12時間""24時間""2日""1週間""なし""0分""1分""5分""10分""15分""20分""25分""30分""45分""1時間""2時間""3時間""12時間""24時間""2日""1週間""ユーザーの言語/地域でのデフォルト設定""土曜日""日曜日""月曜日""予定あり""予定なし""仮承諾""デフォルト""限定公開""一般公開""第1""第2""第3""第4""最終""応答がありません""はい""未定""いいえ""この日の予定のみ""これ以降の予定""すべての予定""これ以降の予定""すべての予定""この予定のみ""繰り返す予定すべて""日""週""月""予定リスト""辞退した場合のみ""辞退したか応答がなかった場合""繰り返し: 毎日""繰り返し: 毎週""繰り返し: 毎月""繰り返し: 毎年""毎月第1日曜日""毎月第2日曜日""毎月第3日曜日""毎月第4日曜日""毎月最終日曜日""毎月第1月曜日""毎月第2月曜日""毎月第3月曜日""毎月第4月曜日""毎月最終月曜日""毎月第1火曜日""毎月第2火曜日""毎月第3火曜日""毎月第4火曜日""毎月最終火曜日""毎月第1水曜日""毎月第2水曜日""毎月第3水曜日""毎月第4水曜日""毎月最終水曜日""毎月第1木曜日""毎月第2木曜日""毎月第3木曜日""毎月第4木曜日""毎月最終木曜日""毎月第1金曜日""毎月第2金曜日""毎月第3金曜日""毎月第4金曜日""毎月最終金曜日""毎月第1土曜日""毎月第2土曜日""毎月第3土曜日""毎月第4土曜日""毎月最終土曜日"
================================================
FILE: library/src/main/res/values-ja/colors.xml
================================================
#ff2222cc#ffcc2222#ff000000#ff2222cc#ffcc2222
================================================
FILE: library/src/main/res/values-ja/strings.xml
================================================
"メールに次を含める:""完了""繰り返し""1度のみ""繰り返す間隔: %d日""繰り返す間隔: %d日""繰り返す間隔: %d週間""繰り返す間隔: %d週間""繰り返す間隔: %dか月""繰り返す間隔: %dか月""繰り返す間隔: %d年""繰り返す間隔: %d年""毎月同じ日""終了日なし""終了日:""%sまで""回数""%d回繰り返す""%d回繰り返す""終了日を変更します"
================================================
FILE: library/src/main/res/values-ko/arrays.xml
================================================
"알림""이메일""SMS""알람""0분""1분""5분""10분""15분""20분""25분""30분""45분""1시간""2시간""3시간""12시간""24시간""2일""1주""없음""0분""1분""5분""10분""15분""20분""25분""30분""45분""1시간""2시간""3시간""12시간""24시간""2일""1주""언어 기본값""토요일""일요일""월요일""바쁨""한가함""미정""기본값""비공개""공개""처음""2번째""3번째""4번째""마지막""응답 없음""예""미정""아니요""이 일정만""이번 및 향후 일정""모든 일정""이번 및 향후 일정""모든 일정""이번 일정만""모든 반복 일정""일""주""월""일정목록""거부한 경우에만 해당""거부했거나 응답이 없는 경우만 해당""매일 반복""매주 반복""매월 반복""매년 반복""매월 첫 번째 일요일""매월 두 번째 일요일""매월 세 번째 일요일""매월 네 번째 일요일""매월 마지막 일요일""매월 첫 번째 월요일""매월 두 번째 월요일""매월 세 번째 월요일""매월 네 번째 월요일""매월 마지막 월요일""매월 첫 번째 화요일""매월 두 번째 화요일""매월 세 번째 화요일""매월 네 번째 화요일""매월 마지막 화요일""매월 첫 번째 수요일""매월 두 번째 수요일""매월 세 번째 수요일""매월 네 번째 수요일""매월 마지막 수요일""매월 첫 번째 목요일""매월 두 번째 목요일""매월 세 번째 목요일""매월 네 번째 목요일""매월 마지막 목요일""매월 첫 번째 금요일""매월 두 번째 금요일""매월 세 번째 금요일""매월 네 번째 금요일""매월 마지막 금요일""매월 첫 번째 토요일""매월 두 번째 토요일""매월 세 번째 토요일""매월 네 번째 토요일""매월 마지막 토요일"
================================================
FILE: library/src/main/res/values-ko/strings.xml
================================================
"이메일:""완료""반복""없음""%d일에 한 번""%d일에 한 번""%d주에 한 번""%d주에 한 번""%d개월에 한 번""%d개월에 한 번""%d년에 한 번""%d년에 한 번""매월 같은 날""계속""특정일까지""종료일: %s""여러 번""%d개의 이벤트""%d개의 이벤트""종료일 변경"
================================================
FILE: library/src/main/res/values-land/dimens.xml
================================================
500dp281dp
================================================
FILE: library/src/main/res/values-lt/arrays.xml
================================================
"Pranešimas""El. paštas""SMS""Signalas""0 min.""1 min.""5 min.""10 min.""15 min.""20 min.""25 min.""30 min.""45 min.""1 val.""2 val.""3 val.""12 val.""24 val.""2 d.""1 sav.""Nėra""0 min.""1 min.""5 min.""10 min.""15 min.""20 min.""25 min.""30 min.""45 min.""1 val.""2 val.""3 val.""12 val.""24 val.""2 d.""1 sav.""Numatytoji lokalė""Šeštadienis""Sekmadienis""Pirmadienis""Užimtas""Pasiekiama""Bandomasis""Numatytasis""Privatus""Viešas""pirmas""antras""trečias""ketvirtas""paskutinis""Nėra atsako""Taip""Galbūt""Ne""Tik šis įvykis""Šis ir būsimi įvykiai""Visi įvykiai""Šis ir būsimi įvykiai""Visi įvykiai""Tik šis įvykis""Visi sekos įvykiai""Diena""Savaitė""Mėnuo""Darbotvarkė""Tik jei atmesta""Jei atmesta ar neatsakyta""KARTOTI KASDIEN""KARTOTI KAS SAVAITĘ""KARTOTI KAS MĖNESĮ""KARTOTI KASMET""kiekvieną pirmą sekmadienį""kiekvieną antrą sekmadienį""kiekvieną trečią sekmadienį""kiekvieną ketvirtą sekmadienį""kiekvieną paskutinį sekmadienį""kiekvieną pirmą pirmadienį""kiekvieną antrą pirmadienį""kiekvieną trečią pirmadienį""kiekvieną ketvirtą pirmadienį""kiekvieną paskutinį pirmadienį""kiekvieną pirmą antradienį""kiekvieną antrą antradienį""kiekvieną trečią antradienį""kiekvieną ketvirtą antradienį""kiekvieną paskutinį antradienį""kiekvieną pirmą trečiadienį""kiekvieną antrą trečiadienį""kiekvieną trečią trečiadienį""kiekvieną ketvirtą trečiadienį""kiekvieną paskut. trečiadienį""kiekvieną pirmą ketvirtadienį""kiekvieną antrą ketvirtadienį""kiekvieną trečią ketvirtadienį""kiekvieną ketv. ketvirtadienį""kiekvieną pask. ketvirtadienį""kiekvieną pirmą penktadienį""kiekvieną antrą penktadienį""kiekvieną trečią penktadienį""kiekvieną ketvirtą penktadienį""kiekvieną paskut. penktadienį""kiekvieną pirmą šeštadienį""kiekvieną antrą šeštadienį""kiekvieną trečią šeštadienį""kiekvieną ketvirtą šeštadienį""kiekvieną paskutinį šeštadienį"
================================================
FILE: library/src/main/res/values-lt/strings.xml
================================================
"Siųsti el. paštu su""Atlikta""Kartoti""Niekada nekartojamas""Kas %d d.""Kas %d d.""Kas %d sav.""Kas %d sav.""Kas %d mėn.""Kas %d mėn.""Kas %d m.""Kas %d m.""kas mėn. tą pačią d.""Visada""Iki nurodytos datos""Iki %s""Vykstant keliems įvykiams""Vykstant %d įvyk.""Vykstant %d įvyk.""keisti pabaigos datą"
================================================
FILE: library/src/main/res/values-lv/arrays.xml
================================================
"Paziņojums""E-pasts""Īsziņa""Signāls""0 minūšu""1 minūte""5 minūtes""10 minūtes""15 minūtes""20 minūtes""25 minūtes""30 minūtes""45 minūtes""1 stunda""2 stundas""3 stundas""12 stundas""24 stundas""2 dienas""1 nedēļa""Nav""0 minūšu""1 minūte""5 minūtes""10 minūtes""15 minūtes""20 minūtes""25 minūtes""30 minūtes""45 minūtes""1 stunda""2 stundas""3 stundas""12 stundas""24 stundas""2 dienas""1 nedēļa""Lokalizācijas noklusējums""Sestdiena""Svētdiena""Pirmdiena""Aizņemts""Pieejams""Pagaidu""Noklusējums""Privāts""Publisks""pirmā""otrā""trešā""ceturtā""pēdējā""Nav atbildes""Jā""Varbūt""Nē""Tikai šo pasākumu""Šis un nākamie pasākumi""Visus pasākumus""Šo un nākamos pasākumus""Visus pasākumus""Tikai šis pasākums""Visus virknes pasākumus""Diena""Nedēļa""Mēnesis""Darba kārtība""Tikai tad, ja tiek noraidīti""Ja tiek noraidīti vai ignorēti""ATKĀRTOT KATRU DIENU""ATKĀRTOT KATRU NED.""ATKĀRTOT KATRU MĒN.""ATKĀRTOT KATRU GADU""katra mēneša pirmajā svētdienā""katra mēneša otrajā svētdienā""katra mēneša trešajā svētdienā""katra mēn. ceturtajā svētdienā""katra mēneša pēdējā svētdienā""katra mēneša pirmajā pirmdienā""katra mēneša otrajā pirmdienā""katra mēneša trešajā pirmdienā""katra mēn. ceturtajā pirmdienā""katra mēneša pēdējā pirmdienā""katra mēneša pirmajā otrdienā""katra mēneša otrajā otrdienā""katra mēneša trešajā otrdienā""katra mēn. ceturtajā otrdienā""katra mēneša pēdējā otrdienā""katra mēneša pirmajā trešdienā""katra mēneša otrajā trešdienā""katra mēneša trešajā trešdienā""katra mēn. ceturtajā trešdienā""katra mēneša pēdējā trešdienā""katra mēn. pirmajā ceturtdienā""katra mēn. otrajā ceturtdienā""katra mēn. trešajā ceturtdienā""katra mēn. ceturt. ceturtdienā""katra mēn. pēdējā ceturtdienā""katra mēn. pirmajā piektdienā""katra mēneša otrajā piektdienā""katra mēn. trešajā piektdienā""katra mēn. ceturt. piektdienā""katra mēneša pēdējā piektdienā""katra mēneša pirmajā sestdienā""katra mēneša otrajā sestdienā""katra mēneša trešajā sestdienā""katra mēn. ceturtajā sestdienā""katra mēneša pēdējā sestdienā"
================================================
FILE: library/src/main/res/values-lv/strings.xml
================================================
"E-pasta ziņojuma adresāts(-i)""Gatavs""Atkārtošana""Bez atkārtošanas""Ik pēc %d dienas""Ik pēc %d dienas(-ām)""Ik pēc %d nedēļas""Ik pēc %d nedēļas(-ām)""Ik pēc %d mēneša""Ik pēc %d mēneša(-iem)""Ik pēc %d gada""Ik pēc %d gada(-iem)""Katru mēnesi""Bezgalīgi""Līdz noteiktam datumam""Līdz šādam datumam: %s""Noteiktu reižu skaitu""%d notikumā""%d notikumos""mainīt beigu datumu"
================================================
FILE: library/src/main/res/values-mcc262/strings.xml
================================================
googlemail.com
================================================
FILE: library/src/main/res/values-ms/arrays.xml
================================================
"Pemberitahuan""E-mel""SMS""Penggera""0 minit""1 minit""5 minit""10 minit""15 minit""20 minit""25 minit""30 minit""45 minit""1 jam""2 jam""3 jam""12 jam""24 jam""2 hari""1 minggu""Tiada""0 minit""1 minit""5 minit""10 minit""15 minit""20 minit""25 minit""30 minit""45 minit""1 jam""2 jam""3 jam""12 jam""24 jam""2 hari""1 minggu""Lalai tempat peristiwa""Sabtu""Ahad""Isnin""Sibuk""Ada""Tentatif""Lalai""Peribadi""Awam""pertama""saat""ketiga""keempat""terakhir""Tiada jawapan""Ya""Mungkin""Tidak""Acara ini sahaja""Acara ini dan acara masa depan""Semua acara""Acara ini & masa depan""Semua acara""Acara ini sahaja""Semua acara dalam siri""Hari""Minggu""Bulan""Agenda""Hanya jika ditolak""Jika ditolak atau tidak dijawab""ULANG SETIAP HARI""ULANG SETIAP MINGGU""ULANG SETIAP BULAN""ULANG SETIAP TAHUN""pada setiap Ahad pertama""pada setiap Ahad kedua""pada setiap Ahad ketiga""pada setiap Ahad keempat""pada setiap Ahad terakhir""pada setiap Isnin pertama""pada setiap Isnin kedua""pada setiap Isnin ketiga""pada setiap Isnin keempat""pada setiap Isnin terakhir""pada setiap Selasa pertama""pada setiap Selasa kedua""pada setiap Selasa ketiga""pada setiap Selasa keempat""pada setiap Selasa terakhir""pada setiap Rabu pertama""pada setiap Rabu kedua""pada setiap Rabu ketiga""pada setiap Rabu keempat""pada setiap Rabu terakhir""pada setiap Khamis pertama""pada setiap Khamis kedua""pada setiap Khamis ketiga""pada setiap Khamis keempat""pada setiap Khamis terakhir""pada setiap Jumaat pertama""pada setiap Jumaat kedua""pada setiap Jumaat ketiga""pada setiap Jumaat keempat""pada setiap Jumaat terakhir""pada setiap Sabtu pertama""pada setiap Sabtu kedua""pada setiap Sabtu ketiga""pada setiap Sabtu keempat""pada setiap Sabtu terakhir"
================================================
FILE: library/src/main/res/values-ms/strings.xml
================================================
"E-mel dengan""Selesai""Ulang""Jangan ulang""Setiap %d hari""Setiap %d hari""Setiap %d minggu""Setiap %d minggu""Setiap %d bulan""Setiap %d bulan""Setiap %d tahun""Setiap %d tahun""hari sama setiap bln""Selamanya""Sehingga tarikh""Sehingga %s""Untuk sejumlah acara""Untuk %d acara""Untuk %d acara""tukar tarikh akhir"
================================================
FILE: library/src/main/res/values-nb/arrays.xml
================================================
"Varsel""E-post""Tekstmelding""Alarm""0 minutter""1 minutt""5 minutter""10 minutter""15 minutter""20 minutter""25 minutter""30 minutter""45 minutter""1 time""To timer""3 timer""12 timer""1 døgn""2 dager""1 uke""Ingen""0 minutter""1 minutt""5 minutter""10 minutter""15 minutter""20 minutter""25 minutter""30 minutter""45 minutter""1 time""2 timer""3 timer""12 timer""1 døgn""2 dager""1 uke""Språkstandard""Lørdag""Søndag""Mandag""Opptatt""Tilgjengelig""Kanskje""Standard""Privat""Offentlig""første""andre""tredje""fjerde""siste""Ingen svar""Ja""Kanskje""Nei""Bare denne hendelsen""Denne og fremtidige aktiviteter""Alle hendelser""Denne og framtidige hendelser""Alle hendelser""Bare denne aktiviteten""Alle hendelser i serien""Dag""Uke""Måned""Agenda""Bare hvis avvist""Hvis avvist eller ikke svart på""GJENTA DAGLIG""GJENTA UKENTLIG""GJENTA MÅNEDLIG""GJENTA ÅRLIG""hver første søndag i måneden""hver andre søndag i måneden""hver tredje søndag i måneden""hver fjerde søndag i måneden""hver siste søndag i måneden""hver første mandag i måneden""hver andre mandag i måneden""hver tredje mandag i måneden""hver fjerde mandag i måneden""hver siste mandag i måneden""hver første tirsdag i måneden""hver andre tirsdag i måneden""hver tredje tirsdag i måneden""hver fjerde tirsdag i måneden""hver siste tirsdag i måneden""hver første onsdag i måneden""hver andre onsdag i måneden""hver tredje onsdag i måneden""hver fjerde onsdag i måneden""hver siste onsdag i måneden""hver første torsdag i måneden""hver andre torsdag i måneden""hver tredje torsdag i måneden""hver fjerde torsdag i måneden""hver siste torsdag i måneden""hver første fredag i måneden""hver andre fredag i måneden""hver tredje fredag i måneden""hver fjerde fredag i måneden""hver siste fredag i måneden""hver første lørdag i måneden""hver andre lørdag i måneden""hver tredje lørdag i måneden""hver fjerde lørdag i måneden""hver siste lørdag i måneden"
================================================
FILE: library/src/main/res/values-nb/strings.xml
================================================
"E-post med""OK""Gjenta""Gjentas aldri""Hver %d. dag""Hver %d. dag""Hver %d. uke""Hver %d. uke""Hver %d. måned""Hver %d. måned""Hvert %d. år""Hvert %d. år""på samme dag hver måned""For alltid""inntil en gitt dato""Til %s""For en rekke aktiviteter""For %d aktivitet""For %d aktiviteter""endre sluttdato"
================================================
FILE: library/src/main/res/values-nl/arrays.xml
================================================
"Melding""E-mail""Sms""Alarm""0 minuten""1 minuut""5 minuten""10 minuten""15 minuten""20 minuten""25 minuten""30 minuten""45 minuten""1 uur""2 uur""3 uur""12 uur""24 uur""2 dagen""1 week""Geen""0 minuten""1 minuut""5 minuten""10 minuten""15 minuten""20 minuten""25 minuten""30 minuten""45 minuten""1 uur""2 uur""3 uur""12 uur""24 uur""2 dagen""1 week""Standaardlandinstelling""Zaterdag""Zondag""Maandag""Bezet""Beschikbaar""Voorlopig""Standaard""Privé""Openbaar""eerste""tweede""derde""vierde""laatste""Geen reactie""Ja""Misschien""Nee""Alleen deze afspraak""Deze en toekomstige afspraken""Alle afspraken""Deze en toekomstige afspraken""Alle afspraken""Alleen deze afspraak""Alle gebeurtenissen in de reeks""Dag""Week""Maand""Agenda""Alleen indien geweigerd""Indien geweigerd of niet gereageerd""DAGELIJKS HERHALEN""WEKELIJKS HERHALEN""MAANDELIJKS HERHALEN""JAARLIJKS HERHALEN""op elke eerste zondag""op elke tweede zondag""op elke derde zondag""op elke vierde zondag""op elke laatste zondag""op elke eerste maandag""op elke tweede maandag""op elke derde maandag""op elke vierde maandag""op elke laatste maandag""op elke eerste dinsdag""op elke tweede dinsdag""op elke derde dinsdag""op elke vierde dinsdag""op elke laatste dinsdag""op elke eerste woensdag""op elke tweede woensdag""op elke derde woensdag""op elke vierde woensdag""op elke laatste woensdag""op elke eerste donderdag""op elke tweede donderdag""op elke derde donderdag""op elke vierde donderdag""op elke laatste donderdag""op elke eerste vrijdag""op elke tweede vrijdag""op elke derde vrijdag""op elke vierde vrijdag""op elke laatste vrijdag""op elke eerste zaterdag""op elke tweede zaterdag""op elke derde zaterdag""op elke vierde zaterdag""op elke laatste zaterdag"
================================================
FILE: library/src/main/res/values-nl/strings.xml
================================================
"E-mail met""Gereed""5 min. uitstellen""Allemaal verwijderen""Snooze""Eenmalige afspraak""; tot %s""; één keer""; %d keer""Dagelijks""Elke %d dagen""Elke werkdag (ma - vr)""Wekelijks op %2$s""Elke %1$d weken op %2$s""Maandelijks""Jaarlijks""Maandelijks (op dag %s)""Jaarlijks (op %s)""Herhalen""Wordt nooit herhaald""Elke %d dag""Elke %d dagen""Elke %d week""Elke %d weken""Elke %d maand""Elke %d maanden""Elk %d jaar""Elke %d jaar""elke maand op dezelfde dag""Voor altijd""Tot een datum""Tot %s""Voor een aantal evenementen""Voor %d evenement""Voor %d evenementen""einddatum wijzigen"
================================================
FILE: library/src/main/res/values-pl/arrays.xml
================================================
"Powiadomienie""E-mail""SMS""Alarm""0 minut""1 minuta""5 minut""10 minut""15 minut""20 minut""25 minut""30 minut""45 minut""1 godzina""2 godziny""3 godziny""12 godzin""24 godziny""2 dni""1 tydzień""Brak""0 minut""1 minuta""5 minut""10 minut""15 minut""20 minut""25 minut""30 minut""45 minut""1 godzina""2 godziny""3 godziny""12 godzin""24 godziny""2 dni""1 tydzień""Domyślny dla regionu""Sobota""Niedziela""Poniedziałek""Zajęty""Dostępny""Wstępnie""Domyślne""Prywatne""Publiczne""1.""2.""3.""4.""ostatni""Brak odpowiedzi""Tak""Może""Nie""Tylko to wydarzenie""To i przyszłe wydarzenia""Wszystkie wydarzenia""To i przyszłe wydarzenia""Wszystkie wydarzenia""Tylko to wydarzenie""Wszystkie wydarzenia w serii""Dzień""Tydzień""Miesiąc""Plan dnia""Tylko po odrzuceniu""Po odrzuceniu lub gdy bez odpowiedzi""CODZIENNIE""CO TYDZIEŃ""CO MIESIĄC""CO ROK""w każdą pierwszą niedzielę""w każdą drugą niedzielę""w każdą trzecią niedzielę""w każdą czwartą niedzielę""w każdą ostatnią niedzielę""w każdy pierwszy poniedziałek""w każdy drugi poniedziałek""w każdy trzeci poniedziałek""w każdy czwarty poniedziałek""w każdy ostatni poniedziałek""w każdy pierwszy wtorek""w każdy drugi wtorek""w każdy trzeci wtorek""w każdy czwarty wtorek""w każdy ostatni wtorek""w każdą pierwszą środę""w każdą drugą środę""w każdą trzecią środę""w każdą czwartą środę""w każdą ostatnią środę""w każdy pierwszy czwartek""w każdy drugi czwartek""w każdy trzeci czwartek""w każdy czwarty czwartek""w każdy ostatni czwartek""w każdy pierwszy piątek""w każdy drugi piątek""w każdy trzeci piątek""w każdy czwarty piątek""w każdy ostatni piątek""w każdą pierwszą sobotę""w każdą drugą sobotę""w każdą trzecią sobotę""w każdą czwartą sobotę""w każdą ostatnią sobotę"
================================================
FILE: library/src/main/res/values-pl/strings.xml
================================================
"E-mail przez""Gotowe""Powtarzanie""Nigdy nie powtarzaj""Co %d dzień""Co %d dni""Co %d tydzień""Co %d tyg.""Co %d miesiąc""Co %d mies.""Co %d rok""Co %d lat(a)""tego samego dnia miesiąca""Bez końca""Do daty""Do %s""Określona liczba powtórzeń""Do %d wydarzenia""Dla %d wydarzeń""zmień datę zakończenia"
================================================
FILE: library/src/main/res/values-pt/arrays.xml
================================================
"Notif.""E-mail""SMS""Alarme""0 minutos""Um minuto""Cinco minutos""10 minutos""15 minutos""20 minutos""25 minutos""30 minutos""45 minutos""Uma hora""Duas horas""Três horas""12 horas""24 horas""Dois dias""Uma semana""Nenhum""0 minutos""Um minuto""5 minutos""10 minutos""15 minutos""20 minutos""25 minutos""30 minutos""45 minutos""Uma hora""Duas horas""Três horas""12 horas""24 horas""Dois dias""Uma semana""Localidade padrão""Sábado""Domingo""Segunda-feira""Ocupado(a)""Disponível""Tentativa""Padrão""Privado""Público""primeiro(a)""segundo(a)""terceiro(a)""quarto(a)""último""Sem resposta""Sim""Talvez""Não""Somente este evento""Este evento e eventos futuros""Todos os eventos""Este evento e eventos futuros""Todos os eventos""Somente este evento""Todos os eventos da série""Dia""Semana""Mês""Compromissos""Somente se recusou""Somente se recusou ou não respondeu""REPETIR DIARIAMENTE""REPETIR SEMANALMENTE""REPETIR MENSALMENTE""REPETIR ANUALMENTE""primeiro domingo do mês""segundo domingo do mês""terceiro domingo do mês""quarto domingo do mês""último domingo do mês""primeira segunda-feira do mês""segunda segunda-feira do mês""terceira segunda-feira do mês""quarta segunda-feira do mês""última segunda-feira do mês""primeira terça-feira do mês""segunda terça-feira do mês""terceira terça-feira do mês""quarta terça-feira do mês""última terça-feira do mês""primeira quarta-feira do mês""segunda quarta-feira do mês""terceira quarta-feira do mês""quarta quarta-feira do mês""última quarta-feira do mês""primeira quinta-feira do mês""segunda quinta-feira do mês""terceira quinta-feira do mês""quarta quinta-feira do mês""última quinta-feira do mês""primeira sexta-feira do mês""segunda sexta-feira do mês""terceira sexta-feira do mês""quarta sexta-feira do mês""última sexta-feira do mês""primeiro sábado do mês""segundo sábado do mês""terceiro sábado do mês""quarto sábado do mês""último sábado do mês"
================================================
FILE: library/src/main/res/values-pt/strings.xml
================================================
"Enviar e-mail para""Concluído""Repetir""Não repetir""A cada %d dia""A cada %d dias""A cada %d semana""A cada %d semanas""A cada %d mês""A cada %d meses""A cada %d ano""A cada %d anos""no mesmo dia de cada mês""Sempre""Até uma data""Até %s""Vários eventos""Por %d evento""Por %d eventos""alterar data de término"
================================================
FILE: library/src/main/res/values-pt-rPT/arrays.xml
================================================
"Notificação""Email""SMS""Alarme""0 minutos""1 minuto""5 minutos""10 minutos""15 minutos""20 minutos""25 minutos""30 minutos""45 minutos""1 hora""2 horas""3 horas""12 horas""24 horas""2 dias""1 semana""Nenhum""0 minutos""1 minuto""5 minutos""10 minutos""15 minutos""20 minutos""25 minutos""30 minutos""45 minutos""1 hora""2 horas""3 horas""12 horas""24 horas""2 dias""1 semana""Local predefinido""Sábado""Domingo""Segunda-feira""Ocupado""Disponível""Tentativa""Predefinido""Particular""Público""primeiro/a""segundo/a""terceiro/a""quarto/a""último""Sem resposta""Sim""Talvez""Não""Apenas este evento""Este e futuros eventos""Todos os eventos""Este e futuros eventos""Todos os eventos""Apenas este evento""Todos os eventos da série""Dia""Semana""Mês""Agenda""Apenas se recusado""Se recusado ou sem resposta""REPETIR DIARIAMENTE""REPETIR SEMANALMENTE""REPETIR MENSALMENTE""REPETIR ANUALMENTE""em cada primeiro domingo""em cada segundo domingo""em cada terceiro domingo""em cada quarto domingo""em cada último domingo""em cada primeira segunda-feira""em cada segunda segunda-feira""em cada terceira segunda-feira""em cada quarta segunda-feira""em cada última segunda-feira""em cada primeira terça-feira""em cada segunda terça-feira""em cada terceira terça-feira""em cada quarta terça-feira""em cada última terça-feira""em cada primeira quarta-feira""em cada segunda quarta-feira""em cada terceira quarta-feira""em cada quarta quarta-feira""em cada última quarta-feira""em cada primeira quinta-feira""em cada segunda quinta-feira""em cada terceira quinta-feira""em cada quarta quinta-feira""em cada última quinta-feira""em cada primeira sexta-feira""em cada segunda sexta-feira""em cada terceira sexta-feira""em cada quarta sexta-feira""em cada última sexta-feira""em cada primeiro sábado""em cada segundo sábado""em cada terceiro sábado""em cada quarto sábado""em cada último sábado"
================================================
FILE: library/src/main/res/values-pt-rPT/strings.xml
================================================
"Enviar email a""Concluído""Repetir""Nunca repete""A cada %d dia""A cada %d dias""A cada %d semana""A cada %d semanas""A cada %d mês""A cada %d meses""A cada %d ano""A cada %d anos""no mesmo dia de cada mês""Para Sempre""Até uma data""Até %s""Durante um n.º de eventos""Para %d evento""Para %d eventos""alterar data de conclusão"
================================================
FILE: library/src/main/res/values-ro/arrays.xml
================================================
"Notificare""E-mail""SMS""Alarmă""0 minute""1 minut""5 minute""10 minute""15 minute""20 de minute""25 de minute""30 de minute""45 de minute""1 oră""2 ore""3 ore""12 ore""24 de ore""2 zile""1 săptămână""Niciunul""0 minute""1 minut""5 minute""10 minute""15 minute""20 de minute""25 de minute""30 de minute""45 de minute""1 oră""2 ore""3 ore""12 ore""24 de ore""2 zile""1 săptămână""Codul local prestabilit""Sâmbătă""Duminică""Luni""Ocupat""Disponibil""Tentativă""Prestabilit""Privat""Public""primul""al doilea""al treilea""al patrulea""ultimul""Niciun răspuns""Da""Poate""Nu""Doar acest eveniment""Acest eveniment şi cele viitoare""Toate evenimentele""Acesta şi evenimentele viitoare""Toate evenimentele""Doar acest eveniment""Toate evenimentele din serie""Zi""Săptămână""Lună""Agendă""Numai dacă sunt respinse""Dacă sunt respinse sau fără răspuns""REPETAȚI ZILNIC""REPETAȚI SĂPTĂMÂNAL""REPETAȚI LUNAR""REPETAȚI ANUAL""în prima duminică din lună""în a doua duminică din lună""în a treia duminică din lună""în a patra duminică din lună""în ultima duminică din lună""în prima luni din lună""în a doua luni din lună""în a treia luni din lună""în a patra luni din lună""în ultima luni din lună""în prima marți din lună""în a doua marți din lună""în a treia marți din lună""în a patra marți din lună""în ultima marți din lună""în prima miercuri din lună""în a doua miercuri din lună""în a treia miercuri din lună""în a patra miercuri din lună""în ultima miercuri din lună""în prima joi din lună""în a doua joi din lună""în a treia joi din lună""în a patra joi din lună""în ultima joi din lună""în prima vineri din lună""în a doua vineri din lună""în a treia vineri din lună""în a patra vineri din lună""în ultima vineri din lună""în prima sâmbătă din lună""în a doua sâmbătă din lună""în a treia sâmbătă din lună""în a patra sâmbătă din lună""în ultima sâmbătă din lună"
================================================
FILE: library/src/main/res/values-ro/strings.xml
================================================
"E-mail cu""Terminat""Repetare""Nu se repetă""O dată la %d zi""O dată la %d zile""O dată la %d săptămână""O dată la %d săptămâni""O dată la %d lună""O dată la %d luni""O dată la %d an""O dată la %d ani""în aceeași zi lunar""Întotdeauna""Până la o anumită dată""Până la %s""De mai multe ori""Pentru %d eveniment""Pentru %d evenimente""schimbați data de încheiere"
================================================
FILE: library/src/main/res/values-ru/arrays.xml
================================================
"Оповещение""Эл. почта""SMS""Сигнал""0 минут""1 минута""5 минут""10 минут""15 минут""20 минут""25 минут""30 минут""45 минут""1 час""2 часа""3 часа""12 часов""24 часа""2 дня""1 неделя""Нет""0 минут""1 минута""5 минут""10 минут""15 минут""20 минут""25 минут""30 минут""45 минут""1 час""2 часа""3 часа""12 часов""24 часа""2 дня""1 неделя""Региональные настройки по умолчанию""суббота""воскресенье""понедельник""Занят""Доступен""Может быть""По умолчанию""Закрытое""Для всех""1""2""3""4""посл.""Не ответили""Да""Может быть""Нет""Только это мероприятие""Это и будущие мероприятия""Все мероприятия""Это и будущие мероприятия""Все мероприятия""Только это мероприятие""Все мероприятия в серии""День""Неделя""Месяц""Повестка дня""Только если отклонено""Если отклонено или нет ответа""ЕЖЕДНЕВНО""ЕЖЕНЕДЕЛЬНО""ЕЖЕМЕСЯЧНО""ЕЖЕГОДНО""первое воскресенье месяца""второе воскресенье месяца""третье воскресенье месяца""четвертое воскресенье месяца""последнее воскресенье месяца""первый понедельник месяца""второй понедельник месяца""третий понедельник месяца""четвертый понедельник месяца""последний понедельник месяца""первый вторник месяца""второй вторник месяца""третий вторник месяца""четвертый вторник месяца""последний вторник месяца""первая среда месяца""вторая среда месяца""третья среда месяца""четвертая среда месяца""последняя среда месяца""первый четверг месяца""второй четверг месяца""третий четверг месяца""четвертый четверг месяца""последний четверг месяца""первая пятница месяца""вторая пятница месяца""третья пятница месяца""четвертая пятница месяца""последняя пятница месяца""первая суббота месяца""вторая суббота месяца""третья суббота месяца""четвертая суббота месяца""последняя суббота месяца"
================================================
FILE: library/src/main/res/values-ru/strings.xml
================================================
"Отправить из""Готово""Повтор""Никогда""Интервал: %d д.""Интервал: %d дн.""Интервал: %d нед.""Интервал: %d нед.""Интервал: %d мес.""Интервал: %d мес.""Интервал: %d г.""Интервал: %d гг./лет""ежемесячно""Всегда""до определенной даты""До %s""несколько раз""Повторов: %d""Повторов: %d""изменить дату окончания"
================================================
FILE: library/src/main/res/values-sk/arrays.xml
================================================
"Upozornenie""E-mail""SMS""Budík""0 minút""1 minúta""5 minút""10 minút""15 minút""20 minút""25 minút""30 minút""45 minút""1 hodina""2 hodiny""3 hodiny""12 hodín""24 hodín""2 dni""1 týždeň""Žiadne""0 minút""1 minúta""5 minút""10 minút""15 minút""20 minút""25 minút""30 minút""45 minút""1 hodina""2 hodiny""3 hodiny""12 hodín""24 hodín""2 dni""1 týždeň""Predvolená hodnota miestneho nastavenia""Sobota""Nedeľa""Pondelok""Zaneprázdnený""K dispozícii""Predbežný""Predvolené""Súkromné""Verejné""prvý""sekunda""tretí""štvrtý""posledné""Bez odpovede""Áno""Možno""Nie""Iba túto udalosť""Túto a budúce udalosti""Všetky udalosti""Túto a budúce udalosti""Všetky udalosti""Iba túto udalosť""Všetky udalosti v rade""Deň""Týždeň""Mesiac""Agenda""Iba ak sú odmietnuté""Ak sú odmietnuté alebo bez odpovede""OPAKOVAŤ DENNE""OPAKOVAŤ TÝŽDENNE""OPAKOVAŤ MESAČNE""OPAKOVAŤ ROČNE""každú prvú nedeľu""každú druhú nedeľu""každú tretiu nedeľu""každú štvrtú nedeľu""každú poslednú nedeľu""každý prvý pondelok""každý druhý pondelok""každý tretí pondelok""každý štvrtý pondelok""každý posledný pondelok""každý prvý utorok""každý druhý utorok""každý tretí utorok""každý štvrtý utorok""každý posledný utorok""každú prvú stredu""každú druhú stredu""každú tretiu stredu""každú štvrtú stredu""každú poslednú stredu""každý prvý štvrtok""každý druhý štvrtok""každý tretí štvrtok""každý štvrtý štvrtok""každý posledný štvrtok""každý prvý piatok""každý druhý piatok""každý tretí piatok""každý štvrtý piatok""každý posledný piatok""každú prvú sobotu""každú druhú sobotu""každú tretiu sobotu""každú štvrtú sobotu""každú poslednú sobotu"
================================================
FILE: library/src/main/res/values-sk/strings.xml
================================================
"Poslať e-mail""Hotovo""Opakovať""Nikdy neopakovať""Raz za %d d.""Raz za %d d.""Raz za %d týžd.""Raz za %d týžd.""Raz za %d mes.""Raz za %d mes.""Raz za %d r.""Raz za %d r.""mesačne v ten istý deň""Stále""Do dátumu""Do %s""Pre určitý počet udalostí""Pre %d udalosť""Pre %d udalosti/-í""zmeniť dátum ukončenia"
================================================
FILE: library/src/main/res/values-sl/arrays.xml
================================================
"Obvestilo""E-pošta""SMS""Alarm""0 minut""1 minuta""5 minut""10 minut""15 minut""20 minut""25 minut""30 minut""45 minut""1 ura""2 uri""3 ure""12 ur""24 ur""2 dni""1 teden""Brez""0 minut""1 minuta""5 minut""10 minut""15 minut""20 minut""25 minut""30 minut""45 minut""1 ura""2 uri""3 ure""12 ur""24 ur""2 dneva""1 teden""Privzete območne nastavitve""Sobota""Nedelja""Ponedeljek""Zasedeno""Na voljo""Začasno""Privzeto""Zasebno""Javno""prvi""sekunda""tretji""četrti""zadnji""Ni odgovora""Da""Morda""Ne""Samo ta dogodek""Ta in prihodnji dogodki""Vsi dogodki""Ti in prihodnji dogodki""Vsi dogodki""Samo ta dogodek""Vsi dogodki v nizu""Dan""Teden""Mesec""Dnevni red""Samo ob zavrnitvi""Ob zavrnitvi ali neodzivanju""PONAVLJAJ VSAK DAN""PONAVLJAJ VSAK TEDEN""PONAVLJAJ VSAK MESEC""PONAVLJAJ VSAKO LETO""vsako prvo nedeljo v mesecu""vsako drugo nedeljo v mesecu""vsako tretjo nedeljo v mesecu""vsako četrto nedeljo v mesecu""vsako zadnjo nedeljo v mesecu""vsak prvi ponedeljek v mesecu""vsak drugi ponedeljek v mesecu""vsak tretji ponedeljek v mes.""vsak četrti ponedeljek v mes.""vsak zadnji ponedeljek v mes.""vsak prvi torek v mesecu""vsak drugi torek v mesecu""vsak tretji torek v mesecu""vsak četrti torek v mesecu""vsak zadnji torek v mesecu""vsako prvo sredo v mesecu""vsako drugo sredo v mesecu""vsako tretjo sredo v mesecu""vsako četrto sredo v mesecu""vsako zadnjo sredo v mesecu""vsak prvi četrtek v mesecu""vsak drugi četrtek v mesecu""vsak tretji četrtek v mesecu""vsak četrti četrtek v mesecu""vsak zadnji četrtek v mesecu""vsak prvi petek v mesecu""vsak drugi petek v mesecu""vsak tretji petek v mesecu""vsak četrti petek v mesecu""vsak zadnji petek v mesecu""vsako prvo soboto v mesecu""vsako drugo soboto v mesecu""vsako tretjo soboto v mesecu""vsako četrto soboto v mesecu""vsako zadnjo soboto v mesecu"
================================================
FILE: library/src/main/res/values-sl/strings.xml
================================================
"Pošlji e-pošto z""Dokončano""Ponovi""Se ne ponovi""Vsakih toliko dni: %d""Vsakih toliko dni: %d""Vsakih toliko tednov: %d""Vsakih toliko tednov: %d""Vsakih toliko mesecev: %d""Vsakih toliko mesecev: %d""Vsakih toliko let: %d""Vsakih toliko let: %d""istega dne vsak mesec""Za vedno""Do datuma""Do %s""Za določeno št. dogodkov""Za toliko dogodkov: %d""Za toliko dogodkov: %d""sprememba končnega datuma"
================================================
FILE: library/src/main/res/values-sr/arrays.xml
================================================
"Обавештење""Е-пошта""SMS""Аларм""0 минута""1 минут""5 минута""10 минута""15 минута""20 минута""25 минута""30 минута""45 минута""1 сат""2 сата""3 сата""12 сати""24 сата""2 дана""1 недеља""Ништа""0 минута""1 минут""5 минута""10 минута""15 минута""20 минута""25 минута""30 минута""45 минута""1 сат""2 сата""3 сата""12 сати""24 сата""2 дана""1 недеља""Подразумевано за локалитет""субота""недеља""понедељак""Заузет/а""Доступан/а""Проба""Подразумевано""Приватно""Јавно""први""други""трећи""четврти""последњи""Без одговора""Да""Можда""Не""Само овај догађај""Овај и будући догађаји""Сви догађаји""Овај и будући догађаји""Сви догађаји""Само овај догађај""Сви догађаји у овом низу""Дан""Недеља""Месец""Распоред""Само за одбијања""За одбијања или догађаје без одговора""ПОНАВЉАЈ ДНЕВНО""ПОНАВЉАЈ НЕДЕЉНО""ПОНАВЉАЈ МЕСЕЧНО""ПОНАВЉАЈ ГОДИШЊЕ""сваке прве недеље""сваке друге недеље""сваке треће недеље""сваке четврте недеље""сваке последње недеље""сваког првог понедељка""сваког другог понедељка""сваког трећег понедељка""сваког четвртог понедељка""сваког последњег понедељка""сваког првог уторка""сваког другог уторка""сваког трећег уторка""сваког четвртог уторка""сваког последњег уторка""сваке прве среде""сваке друге среде""сваке треће среде""сваке четврте среде""сваке последње среде""сваког првог четвртка""сваког другог четвртка""сваког трећег четвртка""сваког четвртог четвртка""сваког последњег четвртка""сваког првог петка""сваког другог петка""сваког трећег петка""сваког четвртог петка""сваког последњег петка""сваке прве суботе""сваке друге суботе""сваке треће суботе""сваке четврте суботе""сваке последње суботе"
================================================
FILE: library/src/main/res/values-sr/strings.xml
================================================
"Пошаљи поруку е-поште за""Готово""Понављање""Нема понављања""На %d дан""На %d дана""На %d недељу""На %d недеље(а)""На %d месец""На %d месеца(и)""На %d годину""На %d године(а)""истог дана сваког месеца""Заувек""До одређеног датума""До %s""За више догађаја""За %d догађај""За %d догађаја""промена крајњег датума"
================================================
FILE: library/src/main/res/values-sv/arrays.xml
================================================
"Meddelande""E-post""SMS""Larm""0 minuter""1 minut""5 minuter""10 minuter""15 minuter""20 minuter""25 minuter""30 minuter""45 minuter""1 timme""2 timmar""3 timmar""12 timmar""24 timmar""2 dagar""1 vecka""Inga""0 minuter""1 minut""5 minuter""10 minuter""15 minuter""20 minuter""25 minuter""30 minuter""45 minuter""1 timme""2 timmar""3 timmar""12 timmar""24 timmar""2 dagar""1 vecka""Standardinställning för språkkod""lördag""söndag""måndag""Upptagen""Tillgänglig""Preliminärt""Standardinställning""Privat""Offentligt""första""andra""tredje""fjärde""senaste""Inget svar""Ja""Kanske""Nej""Bara den här händelsen""Den här och framtida händelser""Alla händelser""Den här och framtida händelser""Alla händelser""Bara den här händelsen""Alla händelser i serien""Dag""Vecka""Månad""Program""Endast vid minskade""Om minskat eller inte svarat""UPPREPA VARJE DAG""UPPREPA VARJE VECKA""UPPREPA VARJE MÅNAD""UPPREPA VARJE ÅR""den första söndagen i månaden""den andra söndagen i månaden""den tredje söndagen i månaden""den fjärde söndagen i månaden""den sista söndagen i månaden""den första måndagen i månaden""den andra måndagen i månaden""den tredje måndagen i månaden""den fjärde måndagen i månaden""den sista måndagen i månaden""den första tisdagen i månaden""den andra tisdagen i månaden""den tredje tisdagen i månaden""den fjärde tisdagen i månaden""den sista tisdagen i månaden""den första onsdagen i månaden""den andra onsdagen i månaden""den tredje onsdagen i månaden""den fjärde onsdagen i månaden""den sista onsdagen i månaden""den första torsdagen i månaden""den andra torsdagen i månaden""den tredje torsdagen i månaden""den fjärde torsdagen i månaden""den sista torsdagen i månaden""den första fredagen i månaden""den andra fredagen i månaden""den tredje fredagen i månaden""den fjärde fredagen i månaden""den sista fredagen i månaden""den första lördagen i månaden""den andra lördagen i månaden""den tredje lördagen i månaden""den fjärde lördagen i månaden""den sista lördagen i månaden"
================================================
FILE: library/src/main/res/values-sv/strings.xml
================================================
"Skicka e-post till""Färdig""Upprepa""Upprepas aldrig""Med %d dags intervall""Med %d dagars intervall""Med %d veckas intervall""Med %d veckors intervall""Med %d månads intervall""Med %d månaders intervall""Med %d års intervall""Med %d års intervall""samma dag varje månad""För alltid""Till ett visst datum""Till den %s""Ett antal upprepningar""För %d event""För %d event""ändra slutdatum"
================================================
FILE: library/src/main/res/values-sw/arrays.xml
================================================
"Arifa""Barua pepe""Ujumbe mfupi""Kengele""Dakika 0""Dakika 1""Dakika 5""Dakika 10""Dakika 15""Dakika 20""Dakika 25""Dakika 30""Dakika 45""Saa 1""Saa 2""Saa 3""Saa 12""Saa 24""Siku 2""Wiki 1""Hamna""Dakika 0""Dakika 1""Dakika 5""Dakika 10""Dakika 15""Dakika 20""Dakika 25""Dakika 30""Dakika 45""Saa 1""Saa 2""Saa 3""Saa 12""Saa 24""Siku 2""Wiki 1""Eneo la kawaida""Jumamosi""Jumapili""Jumatatu""nina shughuli""Ninapatikana""Kujaribia""Chaguo-msingi""Faragha""Umma""kwanza""sekunde""tatu""nne""ya mwisho""Hakuna jibu""Ndio""Labda""Hapana""Tukio hili tu""Hii na matukio ya baadaye""Matukio yote""Tukio hili na yote yajayo""Matukio yote""Tukio hili tu""Matukio yote katika mfululizo""Siku""Wiki""Mwezi""Ajenda""Ikiwa itakataliwa tu""Ikikataliwa au Isipojibiwa""RUDIA KILA SIKU""RUDIA KILA WIKI""RUDIA KILA MWEZI""RUDIA KILA MWAKA""kila Jumapili ya kwanza""kila Jumapili ya pili""kila Jumapili ya tatu""kila Jumapili ya nne""kila Jumapili ya mwisho""kila Jumatatu ya kwanza""kila Jumatatu ya pili""kila Jumatatu ya tatu""kila Jumatatu ya nne""kila Jumatatu ya mwisho""kila Jumanne ya kwanza""kila Jumanne ya pili""kila Jumanne ya tatu""kila Jumanne ya nne""kila Jumanne ya mwisho""kila Jumatano ya kwanza""kila Jumatano ya pili""kila Jumatano ya tatu""kila Jumatano ya nne""kila Jumatano ya mwisho""kila Alhamisi ya kwanza""kila Alhamisi ya pili""kila Alhamisi ya tatu""kila Alhamisi ya nne""kila Alhamisi ya mwisho""kila Ijumaa ya kwanza""kila Ijumaa ya pili""kila Ijumaa ya tatu""kila Ijumaa ya nne""kila Ijumaa ya mwisho""kila Jumamosi ya kwanza""kila Jumamosi ya pili""kila Jumamosi ya tatu""kila Jumamosi ya nne""kila Jumamosi ya mwisho"
================================================
FILE: library/src/main/res/values-sw/strings.xml
================================================
"Tuma barua pepe na""Kwisha""Rudia""Usirudie kamwe""Kila baada ya siku %d""Kila baada ya siku %d""Kila baada ya wiki %d""Kila baada ya wiki %d""Kila baada ya mwezi %d""Kila baada ya miezi %d""Kila baada ya mwaka %d""Kila baada ya miaka %d""katika siku sawa ya kila mwezi""Milele""Hadi tarehe""Hadi %s""Kwa matukio kadhaa""Kwa tukio %d""Kwa matukio %d""badilisha tarehe ya mwisho"
================================================
FILE: library/src/main/res/values-sw600dp/dimens.xml
================================================
300dp480dp
================================================
FILE: library/src/main/res/values-sw600dp-land/dimens.xml
================================================
300dp600dp
================================================
FILE: library/src/main/res/values-th/arrays.xml
================================================
"แจ้งเตือน""อีเมล""SMS""เตือน""0 นาที""1 นาที""5 นาที""10 นาที""15 นาที""20 นาที""25 นาที""30 นาที""45 นาที""1 ชั่วโมง""2 ชั่วโมง""3 ชั่วโมง""12 ชั่วโมง""24 ชั่วโมง""2 วัน""1 สัปดาห์""ไม่มี""0 นาที""1 นาที""5 นาที""10 นาที""15 นาที""20 นาที""25 นาที""30 นาที""45 นาที""1 ชั่วโมง""2 ชั่วโมง""3 ชั่วโมง""12 ชั่วโมง""24 ชั่วโมง""2 วัน""1 สัปดาห์""ตามท้องถิ่น""วันเสาร์""วันอาทิตย์""วันจันทร์""ไม่ว่าง""ว่าง""ยังไม่แน่นอน""เริ่มต้น""ส่วนบุคคล""สาธารณะ""แรก""วินาที""ที่สาม""ที่สี่""สุดท้าย""ไม่มีการตอบกลับ""ใช่""ไม่แน่""ไม่""เฉพาะกิจกรรมนี้""กิจกรรมนี้และในอนาคต""กิจกรรมทั้งหมด""กิจกรรมนี้และในอนาคต""กิจกรรมทั้งหมด""เฉพาะกิจกรรมนี้""กิจกรรมทั้งหมดในชุด""วัน""สัปดาห์""เดือน""กำหนดการ""หากถูกปฏิเสธเท่านั้น""หากถูกปฏิเสธหรือไม่ตอบกลับ""ซ้ำทุกวัน""ซ้ำทุกสัปดาห์""ซ้ำทุกเดือน""ซ้ำทุกปี""ในทุกวันอาทิตย์แรก""ในทุกวันอาทิตย์ที่สอง""ในทุกวันอาทิตย์ที่สาม""ในทุกวันอาทิตย์ที่สี่""ในทุกวันอาทิตย์สุดท้าย""ในทุกวันจันทร์แรก""ในทุกวันจันทร์ที่สอง""ในทุกวันจันทร์ที่สาม""ในทุกวันจันทร์ที่สี่""ในทุกวันจันทร์สุดท้าย""ในทุกวันอังคารแรก""ในทุกวันอังคารที่สอง""ในทุกวันอังคารที่สาม""ในทุกวันอังคารที่สี่""ในทุกวันอังคารสุดท้าย""ในทุกวันพุธแรก""เมื่อทุกวันพุธที่สอง""ในทุกวันพุธที่สาม""ในทุกวันพุธที่สี่""ในทุกวันพุธสุดท้าย""ในทุกวันพฤหัสบดีแรก""ในทุกวันพฤหัสบดีที่สอง""ในทุกวันพฤหัสบดีที่สาม""ในทุกพฤหัสบดีที่สี่""ในทุกวันพฤหัสบดีสุดท้าย""ในทุกวันศุกร์แรก""ในทุกวันศุกร์ที่สอง""ในทุกวันศุกร์ที่สาม""ในทุกวันศุกร์ที่สี่""ในทุกวันศุกร์สุดท้าย""ในทุกวันเสาร์แรก""ในทุกวันเสาร์ที่สอง""ในทุกวันเสาร์ที่สาม""ในทุกวันเสาร์ที่สี่""ในทุกวันเสาร์สุดท้าย"
================================================
FILE: library/src/main/res/values-th/strings.xml
================================================
"ส่งอีเมลด้วย""เสร็จสิ้น""ตั้งซ้ำ""ไม่เกิดซ้ำ""ทุก %d วัน""ทุก %d วัน""ทุก %d สัปดาห์""ทุก %d สัปดาห์""ทุก %d เดือน""ทุก %d เดือน""ทุก %d ปี""ทุก %d ปี""ในวันเดียวกันในแต่ละเดือน""ตลอดไป""จนถึงวันที่""จนถึงวันที่ %s""กำหนดจำนวนกิจกรรม""สำหรับกิจกรรม %d รายการ""สำหรับกิจกรรม %d รายการ""เปลี่ยนวันที่สิ้นสุด"
================================================
FILE: library/src/main/res/values-tl/arrays.xml
================================================
"Notificatn""Email""SMS""Alarma""0 minuto""1 minuto""5 minuto""10 minuto""15 minuto""20 minuto""25 minuto""30 minuto""45 minuto""1 oras""2 oras""3 oras""12 oras""24 oras""2 araw""1 linggo""Wala""0 minuto""1 minuto""5 minuto""10 minuto""15 minuto""20 minuto""25 minuto""30 minuto""45 minuto""1 oras""2 oras""3 oras""12 oras""24 na oras""2 araw""1 linggo""Lokal na default""Sabado""Linggo""Lunes""Abala""Available""Pansamantala""Default""Pribado""Pampubliko""una""segundo""pangatlo""pang-apat""panghuli""Walang tugon""Oo""Maaari""Hindi""Ang kaganapang ito lang""Ito at mga kaganapan sa hinaharap""Lahat ng mg kaganapan""Itong & mga kaganapan sa hinaharap""Lahat ng mga kaganapan""Ang kaganapang ito lamang""Lahat ng mga kaganapan sa serye""Araw""Linggo""Buwan""Agenda""Kung tinanggihan lang""Kung tinanggihan o hindi tinugunan""ULITIN ARAW-ARAW""ULITIN LINGGO-LINGGO""ULITIN BUWAN-BUWAN""ULITIN TAON-TAON""tuwing unang Linggo""tuwing ikalawang Linggo""tuwing ikatlong Linggo""tuwing ikaapat na Linggo""tuwing huling Linggo""tuwing unang Lunes""tuwing ikalawang Lunes""tuwing ikatlong Lunes""tuwing ikaapat na Lunes""tuwing huling Lunes""tuwing unang Martes""tuwing ikalawang Martes""tuwing ikatlong Martes""tuwing ikaapat na Martes""tuwing huling Martes""tuwing unang Miyerkules""tuwing ikalawang Miyerkules""tuwing ikatlong Miyerkules""tuwing ikaapat na Miyerkules""tuwing huling Miyerkules""tuwing unang Huwebes""tuwing ikalawang Huwebes""tuwing ikatlong Huwebes""tuwing ikaapat na Huwebes""tuwing huling Huwebes""tuwing unang Biyernes""tuwing ikalawang Biyernes""tuwing ikatlong Biyernes""tuwing ikaapat na Biyernes""tuwing huling Biyernes""tuwing unang Sabado""tuwing ikalawang Sabado""tuwing ikatlong Sabado""tuwing ikaapat na Sabado""tuwing huling Sabado"
================================================
FILE: library/src/main/res/values-tl/strings.xml
================================================
"Mag-email gamit ang""Tapos na""Ulitin""Hindi nauulit""Bawat %d araw""Bawat %d (na) araw""Bawat %d linggo""Bawat %d (na) linggo""Bawat %d buwan""Bawat %d (na) buwan""Bawat %d taon""Bawat %d (na) taon""pareho araw buwanan""Habambuhay""hanggang tukoy na petsa""Hanggang %s""sa ilang kaganapan""Para sa %d (na) kaganapan""Para sa %d (na) kaganapan""baguhin ang petsa ng pagtatapos"
================================================
FILE: library/src/main/res/values-tr/arrays.xml
================================================
"Bildirim""E-posta""SMS""Alarm""0 dakika""1 dakika""5 dakika""10 dakika""15 dakika""20 dakika""25 dakika""30 dakika""45 dakika""1 saat""2 saat""3 saat""12 saat""24 saat""2 gün""1 hafta""Yok""0 dakika""1 dakika""5 dakika""10 dakika""15 dakika""20 dakika""25 dakika""30 dakika""45 dakika""1 saat""2 saat""3 saat""12 saat""24 saat""2 gün""1 hafta""Varsayılan yerel ayar""Cumartesi""Pazar""Pazartesi""Meşgul""Uygun""Kararsız""Varsayılan""Gizli""Herkese Açık""ilk""ikinci""üçüncü""dördüncü""son""Yanıt yok""Evet""Belki""Hayır""Yalnızca bu etkinlik""Bu ve gelecekteki etkinlikler""Tüm etkinlikler""Bu ve gelecekteki etkinlikler""Tüm etkinlikler""Yalnızca bu etkinlik""Serideki tüm etkinlikler""Gün""Hafta""Ay""Ajanda""Yalnızca reddedildiyse""Reddedildiyse veya yanıt verilmediyse""HER GÜN TEKRARLA""HER HAFTA TEKRARLA""HER AY TEKRARLA""HER YIL TEKRARLA""her ayın ilk Pazar günü""her ayın ikinci Pazar günü""her ayın üçüncü Pazar günü""her ayın dördüncü Pazar günü""her ayın son Pazar günü""her ayın ilk Pazartesi günü""her ayın ikinci Pazartesi günü""her ayın üçüncü Pazartesi günü""her ayın dördüncü Pazartesi günü""her ayın son Pazartesi günü""her ayın ilk Salı günü""her ayın ikinci Salı günü""her ayın üçüncü Salı günü""her ayın dördüncü Salı günü""her ayın son Salı günü""her ayın ilk Çarşamba günü""her ayın ikinci Çarşamba günü""her ayın üçüncü Çarşamba günü""her ayın dördüncü Çarşamba günü""her ayın son Çarşamba günü""her ayın ilk Perşembe günü""her ayın ikinci Perşembe günü""her ayın üçüncü Perşembe günü""her ayın dördüncü Perşembe günü""her ayın son Perşembe günü""her ayın ilk Cuma günü""her ayın ikinci Cuma günü""her ayın üçüncü Cuma günü""her ayın dördüncü Cuma günü""her ayın son Cuma günü""her ayın ilk Cumartesi günü""her ayın ikinci Cumartesi günü""her ayın üçüncü Cumartesi günü""her ayın dördüncü Cumartesi günü""her ayın son Cumartesi günü"
================================================
FILE: library/src/main/res/values-tr/strings.xml
================================================
"E-posta gönder""Bitti""Tekrar""Tekrarlama yok""Her %d günde bir""Her %d günde bir""Her %d haftada bir""Her %d haftada bir""Her %d ayda bir""Her %d ayda bir""Her %d yılda bir""Her %d yılda bir""her ayın aynı gününde""Sonsuza kadar""Belirli bir tarihe kadar""%s tarihine kadar""Belirli sayıda etkinlik""%d etkinlik için""%d etkinlik için""bitiş tarihini değiştir"
================================================
FILE: library/src/main/res/values-uk/arrays.xml
================================================
"Сповіщення""Електронна пошта""SMS""Сигнал""0 хвилин""1 хвилина""5 хвилин""10 хвилин""15 хвилин""20 хвилин""25 хвилин""30 хвилин""45 хвилин""1 година""2 години""3 години""12 годин""24 години""2 дні""1 тиждень""Немає""0 хвилин""1 хвилина""5 хвилин""10 хвилин""15 хвилин""20 хвилин""25 хвилин""30 хвилин""45 хвилин""1 година""2 години""3 години""12 годин""24 години""2 дні""1 тиждень""Код мови за умовч.""Субота""Неділя""Понеділок""Зайнятий""На місці""Під питанням""За умовч.""Приватно""Заг.-дост.""перший""другий""третій""четвертий""останній""Відповіді немає""Так""Можливо""Ні""Лише ця подія""Ця та майбутні події""Усі події""Ця та майбутні події""Усі події""Лише ця подія""Усі події в серіях""День""Тиждень""Місяць""Порядок денний""Лише якщо відхилено""Якщо відхилено або без відповіді""ПОВТОРЮВАТИ ЩОДНЯ""ПОВТОРЮВАТИ ЩОТИЖНЯ""ПОВТОРЮВАТИ ЩОМІСЯЦЯ""ПОВТОРЮВАТИ ЩОРОКУ""кожної першої неділі""кожної другої неділі""кожної третьої неділі""кожної четвертої неділі""кожної останньої неділі""кожного першого понеділка""кожного другого понеділка""кожного третього понеділка""кожного четвертого понеділка""кожного останнього понеділка""кожного першого вівторка""кожного другого вівторка""кожного третього вівторка""кожного четвертого вівторка""кожного останнього вівторка""кожної першої середи""кожної другої середи""кожної третьої середи""кожної четвертої середи""кожної останньої середи""кожного першого четверга""кожного другого четверга""кожного третього четверга""кожного четвертого четверга""кожного останнього четверга""кожної першої п’ятниці""кожної другої п’ятниці""кожної третьої п’ятниці""кожної четвертої п’ятниці""кожної останньої п’ятниці""кожної першої суботи""кожної другої суботи""кожної третьої суботи""кожної четвертої суботи""кожної останньої суботи"
================================================
FILE: library/src/main/res/values-uk/strings.xml
================================================
"Надіслати електронний лист""Готово""Повторити""Не повторюється""Кожен %d день""Кожні %d дн.""Кожен %d тжн.""Інтервал: %d тжн.""Кожен %d міс.""Кожні %d міс.""Кожен %d рік""Кожні %d р.""певного дня щомісяця""Постійно""До певної дати""До %s""Для ряду подій""Для стількох подій: %d""Для стількох подій: %d""змінити дату завершення"
================================================
FILE: library/src/main/res/values-vi/arrays.xml
================================================
"Thông báo""Email""SMS""Báo thức""0 phút""1 phút""5 phút""10 phút""15 phút""20 phút""25 phút""30 phút""45 phút""1 giờ""2 giờ""3 giờ""12 giờ""24 giờ""2 ngày""1 tuần""Không""0 phút""1 phút""5 phút""10 phút""15 phút""20 phút""25 phút""30 phút""45 phút""1 giờ""2 giờ""3 giờ""12 giờ""24 giờ""2 ngày""1 tuần""Ngôn ngữ mặc định""Thứ Bảy""Chủ nhật""Thứ Hai""Bận""Sẵn có""Thử nghiệm""Mặc định""Riêng tư""Công khai""đầu tiên""thứ hai""thứ ba""thứ tư""cuối cùng""Không có phản hồi""Có""Có thể""Không""Chỉ sự kiện này""Sự kiện này và các sự kiện trong tương lai""Tất cả sự kiện""Sự kiện này & các sự kiện trong tương lai""Tất cả sự kiện""Chỉ sự kiện này""Tất cả sự kiện trong hàng loạt sự kiện""Ngày""Tuần""Tháng""Lịch biểu""Chỉ khi bị từ chối""Nếu bị từ chối hoặc không phản hổi""LẶP LẠI HÀNG NGÀY""LẶP LẠI HÀNG TUẦN""LẶP LẠI HÀNG THÁNG""LẶP LẠI HÀNG NĂM""vào mọi Chủ Nhật đầu tiên""vào mọi Chủ Nhật thứ hai""vào mọi Chủ Nhật thứ ba""vào mọi Chủ Nhật thứ tư""vào mọi Chủ Nhật cuối cùng""vào mọi Thứ Hai đầu tiên""vào mọi Thứ Hai thứ hai""vào mọi Thứ Hai thứ ba""vào mọi Thứ Hai thứ tư""vào mọi Thứ Hai cuối cùng""vào mọi Thứ Ba đầu tiên""vào mọi Thứ Ba thứ hai""vào mọi Thứ Ba thứ ba""vào mọi Thứ Ba thứ tư""vào mọi Thứ Ba cuối cùng""vào mọi Thứ Tư đầu tiên""vào mọi Thứ Tư thứ hai""vào mọi Thứ Tư thứ ba""vào mọi Thứ Tư thứ tư""vào mọi Thứ Tư cuối cùng""vào mọi Thứ Năm đầu tiên""vào mọi Thứ Năm thứ hai""vào mọi Thứ Năm thứ ba""vào mọi Thứ Năm thứ tư""vào mọi Thứ Năm cuối cùng""vào mọi Thứ Sáu đầu tiên""vào mọi Thứ Sáu thứ hai""vào mọi Thứ Sáu thứ ba""vào mọi Thứ Sáu thứ tư""vào mọi Thứ Sáu cuối cùng""vào mọi Thứ Bảy đầu tiên""vào mọi Thứ Bảy thứ hai""vào mọi Thứ Bảy thứ ba""vào mọi Thứ Bảy thứ tư""vào mọi Thứ Bảy cuối cùng"
================================================
FILE: library/src/main/res/values-vi/strings.xml
================================================
"Gửi email với""Xong""Lặp lại""Không bao giờ lặp lại""Cứ %d ngày một lần""Cứ %d ngày một lần""Cứ %d tuần một lần""Cứ %d tuần một lần""Cứ %d tháng một lần""Cứ %d tháng một lần""Cứ %d năm một lần""Cứ %d năm một lần""vào cùng một ngày trong mỗi tháng""Vĩnh viễn""Đến một ngày nhất định""Cho đến ngày %s""Đối với một số sự kiện""Cho %d sự kiện""Cho %d sự kiện""thay đổi ngày kết thúc"
================================================
FILE: library/src/main/res/values-zh-rCN/arrays.xml
================================================
"通知""电子邮件""短信""闹钟""0 分钟""1 分钟""5 分钟""10 分钟""15 分钟""20 分钟""25 分钟""30 分钟""45 分钟""1 小时""2 小时""3 小时""12 小时""24 小时""2 天""1 周""无""0 分钟""1 分钟""5 分钟""10 分钟""15 分钟""20 分钟""25 分钟""30 分钟""45 分钟""1 小时""2 小时""3 小时""12 小时""24 小时""2 天""1 周""语言区域的默认设置""星期六""星期日""星期一""忙碌""有空""暂定""默认""私人""公开""第一个""第二个""第三个""第四个""最后一个""无响应""是""可能""否""仅限此活动""此活动和将来的活动""所有活动""此活动和将来的活动""所有活动""仅限此活动""所有重复的活动""日""周""月""日程""仅在您不参加的情况下""在您不参加或未回复的情况下""每天重复""每周重复""每月重复""每年重复""第一个星期日""第二个星期日""第三个星期日""第四个星期日""最后一个星期日""第一个星期一""第二个星期一""第三个星期一""第四个星期一""最后一个星期一""第一个星期二""第二个星期二""第三个星期二""第四个星期二""最后一个星期二""第一个星期三""第二个星期三""第三个星期三""第四个星期三""最后一个星期三""第一个星期四""第二个星期四""第三个星期四""第四个星期四""最后一个星期四""第一个星期五""第二个星期五""第三个星期五""第四个星期五""最后一个星期五""第一个星期六""第二个星期六""第三个星期六""第四个星期六""最后一个星期六"
================================================
FILE: library/src/main/res/values-zh-rCN/strings.xml
================================================
"发送邮件时使用""完成""重复""不重复""每%d天""每%d天""每%d周""每%d周""每%d个月""每%d个月""每%d年""每%d年""在每个月的同一天""无限重复""截至某个日期""截至%s""限定次数""重复%d次""重复%d次""更改结束日期"
================================================
FILE: library/src/main/res/values-zh-rTW/arrays.xml
================================================
"通知""電子郵件""簡訊""鬧鐘""0 分鐘""1 分鐘""5 分鐘""10 分鐘""15 分鐘""20 分鐘""25 分鐘""30 分鐘""45 分鐘""1 小時""2 小時""3 小時""12 小時""24 小時""2 天""1 週""無""0 分鐘""1 分鐘""5 分鐘""10 分鐘""15 分鐘""20 分鐘""25 分鐘""30 分鐘""45 分鐘""1 小時""2 小時""3 小時""12 小時""24 小時""2 天""1 週""地區設定預設值""週六""週日""週一""忙碌""有空""未定""預設""私人""公開""第一個""第二個""第三個""第四個""最後一個""沒有回應""是""不確定""否""僅限此活動""這項活動及未來活動""所有活動""此活動及未來活動""所有活動""僅限這項活動""所有後續活動""天""週""月""待辦事項""僅限拒絕時""拒絕或未回應時""每天重複""每週重複""每月重複""每年重複""每月第一個週日""每月第二個週日""每月第三個週日""每月第四個週日""每月最後一個週日""每月第一個週一""每月第二個週一""每月第三個週一""每月第四個週一""每月最後一個週一""每月第一個週二""每月第二個週二""每月第三個週二""每月第四個週二""每月最後一個週二""每月第一個週三""每月第二個週三""每月第三個週三""每月第四個週三""每月最後一個週三""每月第一個週四""每月第二個週四""每月第三個週四""每月第四個週四""每月最後一個週四""每月第一個週五""每月第二個週五""每月第三個週五""每月第四個週五""每月最後一個週五""每月第一個週六""每月第二個週六""每月第三個週六""每月第四個週六""每月最後一個週六"
================================================
FILE: library/src/main/res/values-zh-rTW/strings.xml
================================================
"寄送電子郵件時使用""完成""提醒方式""不重複進行""每 %d 天""每 %d 天""每 %d 週""每 %d 週""每 %d 個月""每 %d 個月""每 %d 年""每 %d 年""每月的同一天""無限期""直到指定日期為止""結束日期:%s""固定次數重複""重複 %d 次活動""重複 %d 次活動""變更結束日期"
================================================
FILE: library/src/main/res/values-zu/arrays.xml
================================================
"Isaziso""I-imeyili""SMS""I-alamu""0 amaminithi""1 iminithi""5 amaminithi""10 amaminithi""15 amaminithi""20 amaminithi""25 amaminithi""30 amaminithi""45 amaminithi""1 ihora""2 amahora""3 amahora""12 amahora""24 amahora""2 izinsuku""1 iviki""Lutho""0 amaminithi""1 iminithi""5 amaminithi""10 amaminithi""15 amaminithi""20 amaminithi""25 amaminithi""30 amaminithi""45 amaminithi""1 ihora""2 amahora""3 amahora""12 amahora""24 amahora""2 izinsuku""1 iviki""Okuzenzakalelayo kwezici zakhona""Umgqibelo""Isonto""Umsombuluko""Matasa""Yatholakala""Okwesikhashana""Okuzenzakalelayo""Imfihlo""Okusesidlangalaleni""okokuqala""isekhondi""okwesithathu""okwesine""okokugcina""Ayikho impendulo""Yebo""Mhlawumbe""Cha""Kuphela le senzakalo""Lona kanye neyakusasa imicimbi""Zonke izenzakalo""Lokhu & izenzakalo zesikhathi esizayo""Zonke izenzakalo""Kuphela le senzakalo""Zonke izenzakalo ochungechungeni""Usuku""Iviki""Inyanga""Ajenda""Uma ngabe kunqatshelwe kuphela""Uma ngabe kunqatshelwe noma kungaphendulwanga""PHINDA NSUKU ZONKE""PHINDA NGEVIKI""PHINDA NGENYANGA""PHINDA NGONYAKA""njalo ngeSonto lokuqala""njalo ngeSonto lesibili""njalo ngeSonto lesithathu""njalo ngeSonto lesine""njalo ngeSonto lokugcina""njalo ngoMsombuluko wokuqala""njalo ngoMsombuluko wesibili""njalo ngoMsombuluko wesithathu""njalo ngoMsombuluko wesine""njalo ngoMsombuluko wokugcina""njalo ngoLwesibili wokuqala""njalo ngoLwesibili wesibili""njalo ngoLwesibili wesithathu""njalo ngoLwesibili wesine""njalo ngoLwesibili wokugcina""njalo ngoLwesithathu wokuqala""njalo ngoLwesithathu wesibili""njalo ngoLwesithathu wesithathu""njalo ngoLwesithathu wesine""njalo ngoLwesithathu wokugcina""njalo ngoLwesine wokuqala""njalo ngoLwesine wesibili""njalo ngoLwesine wesithathu""njalo ngoLwesine wesine""njalo ngoLwesine wokugcina""njalo ngoLwesihlanu wokuqala""njalo ngoLwesihlanu wesibili""njalo ngoLwesihlanu wesithathu""njalo ngoLwesihlanu wesine""njalo ngoLwesihlanu wokugcina""njalo ngoMgqibelo wokuqala""njalo ngoMgqibelo wesibili""njalo ngoMgqibelo wesithathu""njalo ngoMgqibelo wesine""njalo ngoMgqibelo wokugcina"
================================================
FILE: library/src/main/res/values-zu/strings.xml
================================================
"I-imeyili no""Kwenziwe""Phindaphinda""Awulokothi uphinde""Njalo ngosuku olungu-%d""Njalo ngezinsuku ezingu-%d""Njalo ngeviki elingu-%d""Njalo ngamaviki angu-%d""Njalo ngenyanga engu-%d""Njalo ngezinyanga ezingu-%d""Njalo ngonyaka ongu-%d""Njalo ngeminyaka engu-%d""ngosuku olufanayo njalo ngenyanga""Phakade""Kuze kube idethi ethile""kuze kube ngumhla ka-%s""Okwezinombolo zemicimbi""Okomcimbi ongu-%d""Okwemicimbi engu-%d""shintsha idethi yokugcina"
================================================
FILE: pom.xml
================================================
4.0.0org.sonatype.ossoss-parent9Android Date Time Picker - Parentbe.billington.calendar.recurrencepickerparent1.1.2-SNAPSHOTpomhttp://www.github.com/Shusshu/Android-RecurrencePickerThis library allows you to use the Google Calendar Recurrence pickerRecurrencePicker-projectBenoit Billingtonbenoit.billington@gmail.comUTF-81.75.0_r121librarydemoandroidandroid${android.version}providedjunitjunit4.11org.apache.maven.pluginsmaven-scm-plugin1.7developerConnectioncom.simpligility.maven.pluginsandroid-maven-plugin4.1.1org.apache.maven.pluginsmaven-resources-plugin2.7org.apache.maven.pluginsmaven-compiler-plugin3.2org.apache.maven.pluginsmaven-jarsigner-plugin1.3.2org.apache.maven.pluginsmaven-scm-plugin1.9org.apache.maven.pluginsmaven-checkstyle-plugin2.11conf/maven_checks.xmlfalseorg.apache.maven.pluginsmaven-source-plugin2.4org.apache.maven.pluginsmaven-javadoc-plugin2.10.13.1.1scm:git:git@github.com:Shusshu/Android-RecurrencePicker.gitscm:git:git@github.com:Shusshu/Android-RecurrencePicker.git
masterhttps://github.com/Shusshu/Android-RecurrencePickergithubhttps://github.com/Shusshu/Android-RecurrencePickerThe Apache Software License, Version 2.0http://www.apache.org/licenses/LICENSE-2.0.txtrepo